Android 蓝牙对战五子棋项目实现(含人机对战功能)

上周花了一周时间做的课程设计的项目,实现的功能如下:

基本功能:

(1) 该APP能够通过蓝牙自动搜索周围其他使用了该APP的手机,用户可选择其中某一个APP发起对战的要求,被发起方可以同意或者拒绝;

(2) 双方可以实现五子棋蓝牙对战;

(3) 具备悔棋等功能。

(4) 实现人机对战。提供难度选择。

(5)提供用户战绩排名系统。

项目已经上传到Github:https://github.com/jiangzhengnan/PumpkinGoBang.git

Github跳转

下面是界面截图和实现原理代码分析。

实现部分分为3点:

1、简单人机算法实现。

2、普通人机算法实现。

3、蓝牙模块客户端服务端实现。

一、运行截图:

主界面:

人人对战界面:

蓝牙搜索功能:

蓝牙对战界面:

简单人机功能:

普通人机功能:

二、实现原理:

1、简单难度电脑算法实现:

因为时间比较赶,所以人机算法这块实现得比较简单,没有去学习使用专业的五子棋人机算法,比如五元组分值比较法或者正规的博弈算法。

简单难度算法就是随机在落子点周围生成一个点:

/**
 * 简单模式自动下棋的电脑
 *
 * @param x
 * @param y     玩家下的坐标
 * @param Color 玩家下的棋的颜色    黑12
 *              <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(ArrayList<int[]> 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);
                }
            }
        }
    }
}

2、普通难度算法实现:

普通难度的算法实现地比较纠结,在简单人机的基础上(这里可以称之为“随机落子算法”~!),加入了三点判断功能,就是黑白双方一旦有3点相连会自动往这三点的两端随机堵一个点,并继续递归判断下过的位置,这个循环写得比较长,因为没有把重复的代码抽取出来。

/**
 * 普通模式自动下棋的电脑
 * 12
 *
 * @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<int[]> 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<BluetoothDevice> 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();
    }
}

其他初始化的代码都在项目里面就不赘述了,可以自己下载来看。

*********************************************************我是分割线n(*≧▽≦*)n********************************************************

本来有很多课程设计项目可供选择的= =不过最后还是选了比较有挑战性的这个。

之前一直没接触过蓝牙开发,网上的demo或者例子又都很难理解(可能是没有科学上网的原因)。

最终还是靠着官网的API才慢慢写出了一开始的连接demo,然后一步步测试传输数据。

哎,你们呐,还是要多看API!

时间: 2024-10-05 15:05:53

Android 蓝牙对战五子棋项目实现(含人机对战功能)的相关文章

介绍一款Android小游戏--交互式人机对战五子棋

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6589025 学习Android系统开发之余,编写了一个小游戏--交互式人机对战五子棋,自娱自乐.之所以称之为交互式人机对战五子棋,一是因为在进入人机对战模式这前,你可以任意设置好开局,同时,在对战过程中,你可以看到机器的思考过程,还可以标识出每一个落子点的优劣势:二是因为可以为机器增加游戏经验,使得机器越来越聪明.希望喜欢五子棋的同学能够喜欢,

android蓝牙(二)——接收数据

在蓝牙开发中,我们有这样的一个需求:我们的android客户端要始终保持和蓝牙的连接,当蓝牙有数据返回的时候,android客户端就要及时的收取数据,当蓝牙没有数据返回的时候我们就要保持android客户端和蓝牙之间的连接.这个时候我们就要采取socket来实现和蓝牙之间的连接.做项目使用过http轮询去获取数据,但是发现那样总是有一定的弊端.于是就才用了socket方式去获取数据. 实现步骤:1.启动一个service去监听是否有数据返回.一旦有数据返回就启动一个线程去处理数据 2.处理完数据

Android蓝牙开发的一些经验

转载请注明来自:http://blog.csdn.net/icyfox_bupt/article/details/25487125 最近在实验室做项目,使用了Android的蓝牙开发,这里面有好多坑..所以还是希望能记下来这些东西和大家分享,不要再走我的老路了. 先说一下背景,我是开发手机与带蓝牙的智能设备(蓝牙血压计.血糖仪.手环等)设备对接的APP.也就是说,在设备端没有什么可以操作的,手机负责发起数据传输. 蓝牙连接,不需要配对 由于被曾经使用蓝牙的思路所误导,一直以为使用蓝牙是必须一个配

深入了解Android蓝牙Bluetooth——《进阶篇》

在 [深入了解Android蓝牙Bluetooth--<基础篇>](http://blog.csdn.net/androidstarjack/article/details/60468468)一篇中我们对蓝牙的各个版本的有了一个认识,蓝牙版本的历程及其优劣式介绍.那么接下来咱们就深入一点继续开车进入BLE的进及篇章. 蓝牙BLE4.x BLE分为三部分: Service Characteristic Descriptor 这三部分都用UUID作为唯一标识符.UUID为这种格式:0000ffe1

C 语言控制台实现五子棋项目

花了一天时间实现了控制台五子棋项目,把项目贴上来.也算是告一段落了. 为了进一步了解C语言编程,熟悉优秀的编码风格,提升编码能力,丰富项目经验.所以在编程初期选择了控制台小游戏<单机五子棋>作为项目进行编码. 本项目定位: 控制台小程序,作为熟悉一个完整的项目流程存在. 项目周期: 一星期. 实际时间: 一天.(2016年4月5日) 游戏功能: 首先实现能够让双人进行对战,最后得出胜负(结果).然后加入人机对战元素,也就是传统意义上一个人玩的单机游戏. 编码风格: C语言面向过程编程,变量名与

android -- 蓝牙 bluetooth (一) 入门

前段时间在 网上看了一些关于android蓝牙的文章,发现大部分是基于老版本(4.1以前含4.1)的源码,虽然无碍了解蓝牙的基本原理和工作流程,但对着4.2.2的代码看起来总是有些遗憾.所以针对4.2.2版本代码整理下相关知识,当然蓝牙工作的主干流程是没有变的,上电.加载驱动这些动作少不了的,只是这些功能的实现代码位置变了不少.希望本文可以让大家对android4.2的蓝牙部分代码有一个初步的了解.         正文开始前,先明确代码版本:android  jellyBean 4.2.2,后

深入了解Android蓝牙Bluetooth ——《总结篇》

在我的上两篇博文中讲解了有关android蓝牙的认识以及API的相关的介绍,蓝牙BLE的搜索,连接以及读取. 没有了解的童鞋们请参考: 深入了解Android蓝牙Bluetooth--<基础篇> 深入了解Android蓝牙Bluetooth--<进阶篇> 目前项目中的效果图: 接下来我们就对蓝牙BLE4.0进行一下总结. 蓝牙API Android ble 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用,如果手机系统版本API level

【转】android 蓝牙

前段时间在 网上看了一些关于android蓝牙的文章,发现大部分是基于老版本(4.1以前含4.1)的源码,虽然无碍了解蓝牙的基本原理和工作流程,但对着4.2.2的代码看起来总是有些遗憾.所以针对4.2.2版本代码整理下相关知识,当然蓝牙工作的主干流程是没有变的,上电.加载驱动这些动作少不了的,只是这些功能的实现代码位置变了不少.希望本文可以让大家对android4.2的蓝牙部分代码有一个初步的了解.         正文开始前,先明确代码版本:android  jellyBean 4.2.2,后

【转】android蓝牙开发---与蓝牙模块进行通信--不错

原文网址:http://www.cnblogs.com/wenjiang/p/3200138.html 近半个月来一直在搞android蓝牙这方面,主要是项目需要与蓝牙模块进行通信.开头的进展很顺利,但因为蓝牙模块不在我这里,所以只能用手机测试.一开头就发现手机的蓝牙不能用,为了证明这点,我刷了四次不同不同系统的官方包,正式宣布手机的蓝牙报销了,于是和朋友换手机.在测试的过程中也是非常痛苦,放假了,同学都几乎回家了,剩下的同学中竟然80%都是用非android手机!我和我的小伙伴都吓呆了!!就算