編輯:關於Android編程
上周花了一周時間做的課程設計的項目,實現的功能如下:
人人對戰界面:
藍牙搜索功能:
藍牙對戰界面:

簡單人機功能:
普通人機功能:
二、實現原理:
1、簡單難度電腦算法實現:
因為時間比較趕,所以人機算法這塊實現得比較簡單,沒有去學習使用專業的五子棋人機算法,比如五元組分值比較法或者正規的博弈算法。
簡單難度算法就是隨機在落子點周圍生成一個點:
/**
* 簡單模式自動下棋的電腦
*
* @param x
* @param y 玩家下的坐標
* @param Color 玩家下的棋的顏色 黑1白2
* <p/>
* x&y<GRID_SIZE - 1
*/
private void naocanautomatic(int x, int y, int Color) {
int[][] temp = {{x - 1, y - 1}, {x, y - 1}, {x + 1, y - 1}, {x - 1, y}, {x + 1, y}, {x - 1, y + 1}, {x, y + 1}, {x + 1, y + 1}};
ArrayList<int[]> templist = new ArrayList<>();
for (int i = 0; i < temp.length; i++) {
if (temp[i][0] >= 0 && temp[i][0] < 13 && temp[i][1] >= 0 && temp[i][1] < 13) {
templist.add(temp[i]);
}
}
//判斷是否已經下過
panduanshifouyijingxiaguo(templist);
int num = (int) (Math.random() * templist.size());
int a = templist.get(num)[0];
int b = templist.get(num)[1];
putChess(a, b, Color);
}
這裡要保存已經下過的點位,並判斷是否已經下過,難點是在於如果下的位置在角落處(或周圍已經沒有棋子可以自動生成位置了,這時要遞歸判斷並隨機生成一個新的位置,直到全圖都沒有位置了為止終止遞歸):
/** * 遞歸判斷是否已經下過 * * @param templist */ private void panduanshifouyijingxiaguo(ArrayList2、普通難度算法實現: 普通難度的算法實現地比較糾結,在簡單人機的基礎上(這裡可以稱之為“隨機落子算法”~!),加入了三點判斷功能,就是黑白雙方一旦有3點相連會自動往這三點的兩端隨機堵一個點,並繼續遞歸判斷下過的位置,這個循環寫得比較長,因為沒有把重復的代碼抽取出來。templist) { for (int i = 0; i < storageHadChess.size(); i++) { //如有重復,則刪掉 for (int j = 0; j < templist.size(); j++) { if (storageHadChess.get(i)[0] == templist.get(j)[0] && storageHadChess.get(i)[1] == templist.get(j)[1]) { templist.remove(j); //遞歸防止周圍沒有字落下時直接崩掉 if (templist.size() == 0) { templist.add(new int[]{(int) (Math.random() * (GRID_SIZE - 2)), (int) (Math.random() * (GRID_SIZE - 2))}); // Log.d("whalea", " " + (int) (Math.random() * (GRID_SIZE - 2))); panduanshifouyijingxiaguo(templist); } } } } }
/**
* 普通模式自動下棋的電腦
* 黑1白2
*
* @param x
* @param y
* @param Color
*/
private void normalautomatic(int x, int y, int Color) {
int duishouColor = 0;//對手的顏色
//根據我方顏色推測出對手顏色
if (Color == 1) {
duishouColor = 2;
} else {
duishouColor = 1;
}
//判斷我方是否有3個連成一線了
for (int i = 0; i < GRID_SIZE - 1; i++) //i表示列(根據寬度算出來的)
for (int j = 0; j < GRID_SIZE - 1; j++) { //i表示行(根據高度算出來的)
//檢測橫軸三個相連
if ((((i + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == Color) && (mGridArray[i + 1][j] == Color) && (mGridArray[i + 2][j] == Color)) ||
(((i + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == duishouColor) && (mGridArray[i + 1][j] == duishouColor) && (mGridArray[i + 2][j] == duishouColor))) {
//如果有三個點相連了
//先判斷是否已經測試過這三個點
boolean aa = false;
for (int p = 0; p < cunchusandianArraylist.size(); p++) {
String sandiantemp = cunchusandianArraylist.get(p);
String[] sandiantemps = sandiantemp.split(":");
//如果這三個點已經存在
if ((Integer.parseInt(sandiantemps[0]) == i) &&
(Integer.parseInt(sandiantemps[1]) == j) &&
(Integer.parseInt(sandiantemps[2]) == (i + 1)) &&
(Integer.parseInt(sandiantemps[3]) == j) &&
(Integer.parseInt(sandiantemps[4]) == (i + 2)) &&
(Integer.parseInt(sandiantemps[5]) == j)) {
aa = true;
}
}
if (aa == true) {
} else {
//在兩邊端點位置隨機下一個
ifsangedianxianglian(i - 1, j, i + 3, j, Color);
cunchusandianArraylist.add(i + ":" + j + ":" + (i + 1) + ":" + j + ":" + (i + 2) + ":" + j);
return;
}
}
//縱軸3個相連
if ((((j + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == Color) && (mGridArray[i][j + 1] == Color) && (mGridArray[i][j + 2] == Color)) ||
(((j + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == duishouColor) && (mGridArray[i][j + 1] == duishouColor) && (mGridArray[i][j + 2] == duishouColor))) {
//如果有三個點相連了
//先判斷是否已經測試過這三個點
boolean aa = false;
for (int p = 0; p < cunchusandianArraylist.size(); p++) {
String sandiantemp = cunchusandianArraylist.get(p);
String[] sandiantemps = sandiantemp.split(":");
if ((Integer.parseInt(sandiantemps[0]) == i) &&
(Integer.parseInt(sandiantemps[1]) == j) &&
(Integer.parseInt(sandiantemps[2]) == i) &&
(Integer.parseInt(sandiantemps[3]) == (j + 1)) &&
(Integer.parseInt(sandiantemps[4]) == i) &&
(Integer.parseInt(sandiantemps[5]) == (j + 2))) {
aa = true;
}
}
if (aa == true) {
} else {
//在兩邊端點位置隨機下一個
ifsangedianxianglian(i, j - 1, i, j + 3, Color);
cunchusandianArraylist.add(i + ":" + j + ":" + i + ":" + (j + 1) + ":" + i + ":" + (j + 2));
return;
}
}
//左上到右下3個相連
if ((((j + 3) < (GRID_SIZE - 1)) && ((i + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == Color) && (mGridArray[i + 1][j + 1] == Color) && (mGridArray[i + 2][j + 2] == Color)) ||
(((j + 3) < (GRID_SIZE - 1)) && ((i + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == duishouColor) && (mGridArray[i + 1][j + 1] == duishouColor) && (mGridArray[i + 2][j + 2] == duishouColor))) {
//如果有三個點相連了
//先判斷是否已經測試過這三個點
boolean aa = false;
for (int p = 0; p < cunchusandianArraylist.size(); p++) {
String sandiantemp = cunchusandianArraylist.get(p);
String[] sandiantemps = sandiantemp.split(":");
if ((Integer.parseInt(sandiantemps[0]) == i) &&
(Integer.parseInt(sandiantemps[1]) == j) &&
(Integer.parseInt(sandiantemps[2]) == (i + 1)) &&
(Integer.parseInt(sandiantemps[3]) == (j + 1)) &&
(Integer.parseInt(sandiantemps[4]) == (i + 2)) &&
(Integer.parseInt(sandiantemps[5]) == (j + 2))) {
aa = true;
}
}
if (aa == true) {
} else {
ifsangedianxianglian(i - 1, j - 1, i + 3, j + 3, Color);
cunchusandianArraylist.add(i + ":" + j + ":" + (i + 1) + ":" + (j + 1) + ":" + (i + 2) + ":" + (j + 2));
return;
}
}
//右上到左下3個相連
if ((((i - 3) >= 0) && ((j + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == Color) && (mGridArray[i - 1][j + 1] == Color) && (mGridArray[i - 2][j + 2] == Color)) ||
(((i - 3) >= 0) && ((j + 3) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == duishouColor) && (mGridArray[i - 1][j + 1] == duishouColor) && (mGridArray[i - 2][j + 2] == duishouColor))) {
//如果有三個點相連了
//先判斷是否已經測試過這三個點
boolean aa = false;
for (int p = 0; p < cunchusandianArraylist.size(); p++) {
String sandiantemp = cunchusandianArraylist.get(p);
String[] sandiantemps = sandiantemp.split(":");
if ((Integer.parseInt(sandiantemps[0]) == i) &&
(Integer.parseInt(sandiantemps[1]) == j) &&
(Integer.parseInt(sandiantemps[2]) == (i - 1)) &&
(Integer.parseInt(sandiantemps[3]) == (j + 1)) &&
(Integer.parseInt(sandiantemps[4]) == (i - 2)) &&
(Integer.parseInt(sandiantemps[5]) == (j + 2))) {
aa = true;
}
}
if (aa == true) {
} else {
ifsangedianxianglian(i + 1, j - 1, i - 3, j + 3, Color);
cunchusandianArraylist.add(i + ":" + j + ":" + (i - 1) + ":" + j + 1 + ":" + (i - 2) + ":" + (j + 2));
return;
}
}
}
int[][] temp = {{x - 1, y - 1}, {x, y - 1}, {x + 1, y - 1}, {x - 1, y}, {x + 1, y}, {x - 1, y + 1}, {x, y + 1}, {x + 1, y + 1}};
ArrayList templist = new ArrayList<>();
for (int k = 0; k < temp.length; k++) {
if (temp[k][0] >= 0 && temp[k][0] < 13 && temp[k][1] >= 0 && temp[k][1] < 13) {
templist.add(temp[k]);
}
//判斷是否已經下過
panduanshifouyijingxiaguo(templist);
int num = (int) (Math.random() * templist.size());
int a = templist.get(num)[0];
int b = templist.get(num)[1];
putChess(a, b, Color);
return;
}
}
3、藍牙連接實現代碼:
整個項目是客戶端與服務端一體的,所以藍牙部分大概可以分為三個模塊:
掃描模塊:
實首先打開一個廣播掃描周圍設備:
//接收廣播
/**
* 接受廣播,並顯示尚未配對的可用的周圍所有藍牙設備
*/
private class BluetoothReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//如果是正在掃描狀態
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
//只要BluetoothReceiver接收到來自於系統的廣播,這個廣播是什麼呢,是我找到了一個遠程藍牙設備
//Intent代表剛剛發現遠程藍牙設備適配器的對象,可以從收到的Intent對象取出一些信息
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 如果該設備已經被配對,則跳過
// if (bluetoothDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
if (!devices.contains(bluetoothDevice)) {
//設備數組獲得新的設備信息並更新adapter
deviceNameAndDresss.add(new Device(bluetoothDevice.getName(), bluetoothDevice.getAddress(),bluetoothDevice.getBondState()));
//添加新的設備到設備Arraylist
devices.add(bluetoothDevice);
deviceshowAdapter.notifyDataSetChanged();
}
}
}
}
也可以調用BlueToothAapter的startDiscovery()方法主動進行掃描:
//掃描周圍的藍牙設備按鈕監聽器
private class SaoMiaoButtonListener implements View.OnClickListener {
@Override
public void onClick(View v) {
ObjectAnimator animator = ObjectAnimator.ofFloat(v,"rotation",0,359);
animator.setRepeatCount(12);
animator.setDuration(1000);
animator.start();
isQuering = true;
Toast.makeText(BlueToothFindOthersAty.this, "開始掃描", Toast.LENGTH_SHORT).show();
//清空列表
deviceNameAndDresss.clear();
//獲得已配對的藍牙設備
Set pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if (!devices.contains(device)) {
deviceNameAndDresss.add(new Device(device.getName(), device.getAddress(),device.getBondState()));
devices.add(device);
}
}
}
deviceshowAdapter.setDevices(deviceNameAndDresss);
deviceshowAdapter.notifyDataSetChanged();
//開始掃描周圍的可見的藍牙設備
bluetoothAdapter.startDiscovery();
}
}
服務端等待連接模塊:
這裡服務端比較簡單,通過accpet方法監聽連接就可以了。
//開啟子線程等待連接
new Thread(new Runnable() {
@Override
public void run() {
try {
//開啟服務端
//等待客戶端接入
while (true) {
bluetoothServerSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(benjiname, Config.UUID);
fuwuSocket = bluetoothServerSocket.accept();
if (fuwuSocket.isConnected()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BlueToothFindOthersAty.this, "接收挑戰請求,建立連接成功!", Toast.LENGTH_SHORT);
//執行socket方法
BlueToothGameAty blueToothGameAty = new BlueToothGameAty();
blueToothGameAty.blueToothGameAty.manageConnectedSocket(fuwuSocket, false);
// blueToothGameAty.blueToothGameAty.chushihua(blueToothGameAty);
}
});
//跳轉到藍牙游戲activity
Intent i = new Intent(BlueToothFindOthersAty.this,BlueToothGameAty.class);
startActivity(i);
//初始化線程來傳輸數據
// manageConnectedSocket(fuwuSocket);
//得到連接之後關閉ServerSocket
// bluetoothServerSocket.close();
//打斷線程
// Thread.interrupted();
}
}
} catch (IOException e) {
e.printStackTrace();
Log.d("whalea", "沒讀到的原因!:" + e.getMessage());
}
}
}).start();
客戶端主動連接模塊:
客戶端socket使用connet()方法主動連接。
/**
* 建立連接的方法
*
* @param position 位置
* @param isfaqiren
*/
private void buildConnect(int position, boolean isfaqiren) {
//自己主動去連接
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(deviceNameAndDresss.get(position).getDeviceAddress());
Boolean result = false;
try {
//先進行配對
//如果沒有配對
Log.d("whalea", "開始配對");
if (device.getBondState() == BluetoothDevice.BOND_NONE) {
Method createBondMethod = null;
createBondMethod = BluetoothDevice.class
.getMethod("createBond");
Log.d("whalea", "開始配對");
result = (Boolean) createBondMethod.invoke(device);
}
//如果已經配對好了
else if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
//獲得客戶端Socket
kehuduanSocket = device.createRfcommSocketToServiceRecord(Config.UUID);
final AlertDialog aDialog = new AlertDialog.Builder(BlueToothFindOthersAty.this).
setTitle("發起對戰").
setMessage("確認挑戰玩家:" + deviceNameAndDresss.get(position).getDeviceName() + "嗎?")
.setNegativeButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new Thread(new Runnable() {
@Override
public void run() {
//先停止掃描,以防止之後的連接被阻塞
bluetoothAdapter.cancelDiscovery();
try {
//開始連接,發送連接請求
kehuduanSocket.connect();
if (!bluetoothAdapter.isEnabled()) {
bluetoothAdapter.enable();
}
if (kehuduanSocket.isConnected()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BlueToothFindOthersAty.this, "連接成功!!", Toast.LENGTH_SHORT).show();
//執行socket方法
BlueToothGameAty blueToothGameAty = new BlueToothGameAty();
blueToothGameAty.blueToothGameAty.manageConnectedSocket(kehuduanSocket, true);
// blueToothGameAty.blueToothGameAty.chushihua(blueToothGameAty);
}
});
//跳轉到藍牙游戲activity
Intent i = new Intent(BlueToothFindOthersAty.this,BlueToothGameAty.class);
startActivity(i);
}
} catch (final IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BlueToothFindOthersAty.this, "連接失敗!!" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
/* try {
kehuduanSocket.close();
} catch (IOException e1) {
}
return;*/
}
// manageConnectedSocket(kehuduanSocket);
//之後關閉socket,清除內部資源
/* try {
kehuduanSocket.close();
} catch (IOException e) {
e.printStackTrace();
}*/
}
}).start();
}
})
.setPositiveButton("取消", null).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
其他初始化的代碼都在項目裡面就不贅述了,可以自己下載來看。
Android studio下增量升級功能的NDK開發
最近研究Android應用的增量升級功能,期間涉及到了NDK開發的內容,整理記錄在此。先說幾個問題。一、NDK開發就是JNI開發啊,臥槽我原來都不知道啊,一直以為是兩個東
QQ掃描沒有出現AR火炬怎麼辦
qq火炬手是騰訊QQ針對今年的巴西裡約奧運會推出的火炬傳遞活動,最近,越來越多的小伙伴參與了QQ火炬手的活動,因此也發現了很多問題,比如QQ掃描沒有出現AR
安卓柱狀圖
今天做項目需要用到簡單的橫向的柱狀圖,上網查了一下,沒找到合適的框架,於是決定自己動手寫一個自定義View,來實現三種柱狀圖。那麼先看效果圖橫向的柱狀圖,只有柱子的比例和
android ExpandableListView三級菜單的使用
由於本人所作的項目需要用到這種列表式的收縮與展開,因此,就好好研究了有關這方面的一些知識,當然,也借鑒了網上一些成功的案列。下面就是我模擬測試的一個展示界面。 實現上面的