Да, я видел. Но не подхожу под условия заявленные там.Есть ветка посвящённая этому
Вопрос закрыл.C Attiny работает не стабильно, stm через раз читает правильно
Control register 1 (USART_CR1)
Bit 10 PCE: Parity control
0: Parity control disabled
1: Parity control enabled
Bit 9 PS: Parity selection
This bit selects the odd or even parity when the parity generation/detection is enabled (PCE
bit set). It is set and cleared by software. The parity will be selected after the current byte.
0: Even parity
1: Odd parity
USART1->CR1 |= USART_CR1_PCE;
USART1->CR1 &=~ USART_CR1_PS;
Биты UPM1 и UPM0 (USART Parity Mode) в регистре UCSRC отвечают за включение и тип контроля чётности:
//Если бит UMSEL сброшен в 0, то модуль работает в асинхронном режиме
//USBS Количество стопбитов. Если бит сброшен в 0, то передатчик посылает 1 стопбит,
//если установлен в 1, то 2 стопбита.
//UCPOL При работе в асинхронном режиме он должен быть сброшен в 0. USART Mode: Asynchronous
//UPM1 UPM0 - Управление схемой контроля четности - 0 0 Выключена
UCSRC &= ~((1 << UMSEL) | (1 << USBS) | (1 << UCPOL) | (1 << UPM1) | (1 << UPM0)); // Clear bit
// Настройка формата кадра:
// - Even parity (UPM1=1, UPM0=0)
// - 8 бит данных (UCSZ1=1, UCSZ0=1)
// - 1 стоп‑бит (USBS=0)
UCSRC |= (1 << UPM1); // Set bits
//Определение размера слова данных - 8 бит
UCSRC |= (1 << UCSZ1) | (1 << UCSZ0); // Set bits
UCSRA &= ~(1 << UCSZ2); // Clear bit
//enable clock access to GPIOA
RCC->APB2ENR|=RCC_APB2ENR_IOPAEN;
//Enable clock access to alternate function
RCC->APB2ENR|=RCC_APB2ENR_AFIOEN;
//Настраиваем порт в режим альтернативной функции
GPIOA->CRH &= ~(GPIO_CRH_MODE8_Msk | GPIO_CRH_CNF8_Msk); //Сбрасываем биты в ноль
GPIOA->CRH |= (0x03 << GPIO_CRH_MODE8_Pos) | (0x02 << GPIO_CRH_CNF8_Pos); //устанавливаем нужные биты
RCC->CFGR &= ~(RCC_CFGR_MCO_Msk); //Сначала устанавливаем все в ноль
//Настройка вывода тактового сигнала
//через MCO-пин
//sourse - источник тактирования
// 0 - отключено
// 4 - SYSCLK
// 5 - HSI
// 6 - HSE
// 7 - PLL/2
RCC->CFGR |= (6<<RCC_CFGR_MCO_Pos); //Устанавливаем источник тактирования


Нашел несколько статей - изучаю.Как используя MAX7219 вместо одного светодиода поставить четыре?
Не понятно, как вы собираетесь размещать "четыре на одно поле". Если поставить светодиоды в углах клеток (на пересечении линий), то задача сведется к управлению матрицей 9 x 9, что невозможно сделать на одной MAX7219, но можно или на двух MAX7219, Или на трех сдвиговых регистрах. Так же влияет, сколько одновременно клеток может быть подсвечено, какие используются светодиоды и т.д.Одного светодиода для подсветки поля доски не достаточно. Нужно четыре на одно поле.
cellX и cellY (от 0 до 7).(cellX, cellY), (cellX+1, cellY), (cellX, cellY+1), (cellX+1, cellY+1).for (int row = 0; row < 9; row++) {
// 1. Гасим всё
turnOffAllRows();
turnOffAllCols();
// 2. Проверяем, относится ли текущая строка к углам выбранной клетки
if (row == cellY || row == cellY + 1) {
// 3. Включаем нужные столбцы
turnOnCol(cellX);
turnOnCol(cellX + 1);
// 4. Включаем текущую строку
turnOnRow(row);
}
// 5. Задержка для мультиплексирования (около 2-3 мс на строку)
delayMicroseconds(2000);
}
Как то такНе понятно, как вы собираетесь размещать "четыре на одно поле".
Нет, клетки подсвечиваются под фигурами, итого одновременно может светится 32 клетки.В каждый момент времени подсвечивается не более одной клетки



void max7219_init() {
write_reg(DISPLAY_TEST_REG, 0);
write_reg(SCAN_LIMIT_REG, 7);
write_reg(DECODE_MODE_REG, 0);
write_reg(SHUTDOWN_REG, 1);
clear();
}

void max7219_init() {
write_reg(DISPLAY_TEST_REG, 0);
write_reg(SCAN_LIMIT_REG, 7);
write_reg(DECODE_MODE_REG, 0);
write_reg(INTENSITY_REG, 15);
write_reg(SHUTDOWN_REG, 1);
clear();
}

Как лучше все это собрать?




package com.example.touchChess;
import com.example.touchChess.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends View {
Paint paint;
Bitmap bitmap1,bitmap2;
public DrawView(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.board);
bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.peice);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
canvas.drawBitmap(bitmap1, 0, 0, paint);
canvas.drawBitmap(bitmap2, 25, 525, paint);
}
}
}


package com.example.touchChess;
import com.example.touchChess.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends View {
Paint paint;
Bitmap bitmap1,bitmap2;
Bitmap[] arrayOfBitmap = new Bitmap[12];
public DrawView(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//доска
bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.board);
//фигуры
bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.peice);
/*
createBitmap(Bitmap source, int x, int y, int width, int height) - Returns an immutable bitmap from the specified subset of the source bitmap.
*/
for(int i = 0; i < 6; i++) {
//черные
arrayOfBitmap[i] = Bitmap.createBitmap(bitmap2, i*60,60,60, 60);
//белые
arrayOfBitmap[i+6] = Bitmap.createBitmap(bitmap2, i*60,0,60, 60);
}
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
//доска
canvas.drawBitmap(bitmap1, 0, 0, paint);
//пример начальной позиции
//король
canvas.drawBitmap(arrayOfBitmap[0], 266, 22, paint);
canvas.drawBitmap(arrayOfBitmap[6], 266, 442, paint);
//ферзь
canvas.drawBitmap(arrayOfBitmap[1], 206, 22, paint);
canvas.drawBitmap(arrayOfBitmap[7], 206, 442, paint);
//слон
canvas.drawBitmap(arrayOfBitmap[3], 326, 22, paint);
canvas.drawBitmap(arrayOfBitmap[3], 146, 22, paint);
canvas.drawBitmap(arrayOfBitmap[9], 326, 442, paint);
canvas.drawBitmap(arrayOfBitmap[9], 146, 442, paint);
//конь
canvas.drawBitmap(arrayOfBitmap[4], 386, 22, paint);
canvas.drawBitmap(arrayOfBitmap[4], 86, 22, paint);
canvas.drawBitmap(arrayOfBitmap[10], 386, 442, paint);
canvas.drawBitmap(arrayOfBitmap[10], 86, 442, paint);
//ладья
canvas.drawBitmap(arrayOfBitmap[2], 446, 22, paint);
canvas.drawBitmap(arrayOfBitmap[2], 26, 22, paint);
canvas.drawBitmap(arrayOfBitmap[8], 446, 442, paint);
canvas.drawBitmap(arrayOfBitmap[8], 26, 442, paint);
//пешки
for(int i = 0; i < 8; i++)
{
canvas.drawBitmap(arrayOfBitmap[5], 26+i*60, 82, paint);
canvas.drawBitmap(arrayOfBitmap[11], 26+i*60, 382, paint);
}
}
}
}



package com.example.touchChess;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.example.touchChess.R;
import org.apache.commons.net.telnet.TelnetInputListener;
import org.apache.commons.net.telnet.TelnetNotificationHandler;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends Activity implements TelnetInputListener{
private TelnetConnection mConnection;
private BufferedInputStream mInputBuffer;
private TextView mTextViewContent;
private ScrollView mScrollViewContent;
private String mServerPort;
private String mServerAddress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(new DrawView(this));
setContentView(R.layout.activity_main);
FrameLayout container = findViewById(R.id.boardContainer);
container.addView(new DrawView(this));
mServerPort = "8880";
mServerAddress = "192.168.4.1";
mInputBuffer = null;
mConnection = new TelnetConnection();
mConnection.getConnection().setReaderThread(true);
mConnection.getConnection().registerInputListener(this);
mScrollViewContent = (ScrollView)findViewById(R.id.scrollViewContent);
mTextViewContent = (TextView)findViewById(R.id.textViewContent);
}
public void telnetInputAvailable() {
if(mConnection.isConnected()) {
try {
while (mInputBuffer.available() > 0) {
final String s = Character.toString((char) mInputBuffer.read());
runOnUiThread(new Runnable() {
public void run() {
mTextViewContent.append(s);
}
});
}
mScrollViewContent.post(new Runnable() {
public void run() {
mScrollViewContent.fullScroll(View.FOCUS_DOWN);
}
});
}
catch (IOException e) {
}
}
}
class DrawView extends View {
Paint paint;
Bitmap bitmap1, bitmap2;
Bitmap[] arrayOfBitmap = new Bitmap[12];
public DrawView(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// доска
bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.board);
// фигуры
bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.peice);
/*
createBitmap(Bitmap source, int x, int y, int width, int height) - Returns an immutable bitmap from the specified subset of the source bitmap.
*/
for (int i = 0; i < 6; i++) {
// черные
arrayOfBitmap[i] = Bitmap.createBitmap(bitmap2, i * 60, 60, 60, 60);
// белые
arrayOfBitmap[i + 6] = Bitmap.createBitmap(bitmap2, i * 60, 0, 60, 60);
}
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
// доска
canvas.drawBitmap(bitmap1, 0, 0, paint);
// пример начальной позиции
// король
canvas.drawBitmap(arrayOfBitmap[0], 266, 22, paint);
canvas.drawBitmap(arrayOfBitmap[6], 266, 442, paint);
// ферзь
canvas.drawBitmap(arrayOfBitmap[1], 206, 22, paint);
canvas.drawBitmap(arrayOfBitmap[7], 206, 442, paint);
// слон
canvas.drawBitmap(arrayOfBitmap[3], 326, 22, paint);
canvas.drawBitmap(arrayOfBitmap[3], 146, 22, paint);
canvas.drawBitmap(arrayOfBitmap[9], 326, 442, paint);
canvas.drawBitmap(arrayOfBitmap[9], 146, 442, paint);
// конь
canvas.drawBitmap(arrayOfBitmap[4], 386, 22, paint);
canvas.drawBitmap(arrayOfBitmap[4], 86, 22, paint);
canvas.drawBitmap(arrayOfBitmap[10], 386, 442, paint);
canvas.drawBitmap(arrayOfBitmap[10], 86, 442, paint);
// ладья
canvas.drawBitmap(arrayOfBitmap[2], 446, 22, paint);
canvas.drawBitmap(arrayOfBitmap[2], 26, 22, paint);
canvas.drawBitmap(arrayOfBitmap[8], 446, 442, paint);
canvas.drawBitmap(arrayOfBitmap[8], 26, 442, paint);
// пешки
for (int i = 0; i < 8; i++) {
canvas.drawBitmap(arrayOfBitmap[5], 26 + i * 60, 82, paint);
canvas.drawBitmap(arrayOfBitmap[11], 26 + i * 60, 382, paint);
}
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutActionBar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorUnder"
android:orientation="vertical">
<Button
android:id="@+id/buttonConnect"
android:text="@string/stringConnect"
android:layout_width="100dp"
android:layout_height="30dp"
android:layout_marginTop="10dp"
android:gravity="center"
android:layout_above="@+id/editTextCommand"
style="@style/ConnectButton">
</Button>
</RelativeLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:background="@color/colorUnder">
<EditText
android:id="@+id/editTextCommand"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:hint="@string/stringCommand"
android:maxLines="1"
android:layout_weight=".45">
</EditText>
<Button
android:id="@+id/buttonSend"
android:text="@string/stringSend"
android:layout_width="100dp"
android:layout_marginTop="5dp"
android:layout_height="wrap_content">
</Button>
</LinearLayout>
<FrameLayout
android:id="@+id/boardContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
<ScrollView
android:id="@+id/scrollViewContent"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:background="@color/colorUnder"
android:layout_weight="1">
<TextView
android:id="@+id/textViewContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="7dp"
android:background="@color/colorUnder"
android:textColorLink="@color/colorUnderBar"
android:textColor="@color/colorDark"
android:typeface="monospace"
android:text="@string/waiting_esp"/>
</ScrollView>
</LinearLayout>
<resources>
<string name="app_name">touchChess</string>
<string name="title_activity_main">MAIN_ACTIVITY</string>
<string name="stringCommand">Enter command here</string>
<string name="stringSend">SEND</string>
<string name="stringConnect">CONNECT</string>
<string name="waiting_esp">Ожидание данных от ESP8266...</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorGreen">#00ff00</color>
<color name="colorBlue">#0000ff</color>
<color name="colorWhite">#ffffff</color>
<color name="colorBlack">#000000</color>
<color name="colorDark">#111111</color>
<color name="colorDarkGray">#444444</color>
<color name="colorGray">#a0a0a0</color>
<color name="colorLiteGray">#e0e0e0</color>
<color name="colorDarkGreen">#007700</color>
<color name="colorHoloBlue">#ff33b5e5</color>
<color name="colorButtonBackground">#d6d7d7</color>
<color name="colorButtonText">#1c1c1c</color>
<color name="colorUnderBar">#009688</color>
<color name="colorUnder">#CAEAF9</color>
</resources>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="@android:style/Theme.Light" />
<style name="ConnectButton" parent="@android:style/Widget.Button">
<item name="android:gravity">center</item>
<item name="android:textColor">@color/colorWhite</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">normal</item>
<item name="android:background">@color/colorDark</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
</style>
</resources>

package com.example.touchChess;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.AsyncTask;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import android.view.MotionEvent;
import android.graphics.Canvas;
import com.example.touchChess.R;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.InetSocketAddress;
public class MainActivity extends Activity {
public int touchX, touchY;
public Canvas canvasBmp3;
public Bitmap[] arrayOfBitmap = new Bitmap[12];
public Bitmap bitmap1, bitmap2,bitmap3,bitmap4;
public Paint paint;
public String StrFen, subStrFen;
// Сеть
private Socket mSocket;
private InputStream mInputBuffer;
private OutputStream mOutputBuffer;
private Thread mReaderThread;
private volatile boolean mIsReading = false;
// Адрес
private String mServerPort = "8880";
private String mServerAddress = "192.168.4.1";
// UI
private TextView mTextViewContent;
private ScrollView mScrollViewContent;
private Button mButtonConnect;
private Button mButtonSend;
private EditText mEditTextCommand;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrFen = getString(R.string.perft0);
FrameLayout container = findViewById(R.id.boardContainer);
container.addView(new DrawView(this));
mScrollViewContent = (ScrollView) findViewById(R.id.scrollViewContent);
mTextViewContent = (TextView) findViewById(R.id.textViewContent);
mButtonConnect = (Button) findViewById(R.id.buttonConnect);
mButtonConnect.requestFocus();
mButtonSend = (Button) findViewById(R.id.buttonSend);
mEditTextCommand = (EditText) findViewById(R.id.editTextCommand);
mButtonConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new ConnectTask().execute();
}
});
mButtonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String cmd = mEditTextCommand.getText().toString().trim();
if (cmd.isEmpty()) {
ShowAlert("Введите команду");
return;
}
new SendTask().execute(cmd);
}
});
}
private boolean isConnected() {
return mSocket != null && mSocket.isConnected() && !mSocket.isClosed();
}
private class ConnectTask extends AsyncTask<Void, Void, Boolean> {
private String errorMessage = null;
@Override
protected Boolean doInBackground(Void... arg0) {
if (!isConnected()) {
try {
mSocket = new Socket();
mSocket.connect(
new InetSocketAddress(mServerAddress, Integer.parseInt(mServerPort)),
5000
);
mInputBuffer = mSocket.getInputStream();
mOutputBuffer = mSocket.getOutputStream();
startReaderThread();
return true;
} catch (Exception e) {
errorMessage = e.getClass().getName() + ": " +
(e.getMessage() != null ? e.getMessage() : "no message");
return false;
}
} else {
stopReaderThread();
closeSocket();
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
updateConnectionStatus(result);
if (errorMessage != null) ShowAlert(errorMessage);
}
}
private class SendTask extends AsyncTask<String, Void, Boolean> {
private String errorMessage = null;
@Override
protected Boolean doInBackground(String... params) {
if (!isConnected()) {
errorMessage = "Нет соединения";
return false;
}
String command = params[0] + "\r\n";
try {
mOutputBuffer.write(command.getBytes("UTF-8"));
mOutputBuffer.flush();
return true;
} catch (Exception e) {
errorMessage = e.getClass().getName() + ": " +
(e.getMessage() != null ? e.getMessage() : "no message");
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
if (!result && errorMessage != null) {
ShowAlert(errorMessage);
}
}
}
private void startReaderThread() {
mIsReading = true;
mReaderThread = new Thread(new Runnable() {
@Override
public void run() {
while (mIsReading && mInputBuffer != null) {
try {
int available = mInputBuffer.available();
if (available > 0) {
byte[] buffer = new byte[available];
int bytesRead = mInputBuffer.read(buffer);
if (bytesRead > 0) {
final String s = new String(buffer, 0, bytesRead, "UTF-8");
runOnUiThread(new Runnable() {
public void run() {
if (mTextViewContent != null) {
mTextViewContent.append(s);
}
}
});
mScrollViewContent.post(new Runnable() {
public void run() {
mScrollViewContent.fullScroll(View.FOCUS_DOWN);
}
});
}
} else {
Thread.sleep(50);
}
} catch (IOException e) {
break;
} catch (InterruptedException e) {
break;
}
}
}
});
mReaderThread.start();
}
private void stopReaderThread() {
mIsReading = false;
if (mReaderThread != null) {
mReaderThread.interrupt();
try {
mReaderThread.join(1000); // ждём до 1 секунды на завершение
} catch (InterruptedException ignored) {}
mReaderThread = null;
}
}
// Вспомогательный метод для закрытия сокета
private void closeSocket() {
try {
if (mSocket != null && !mSocket.isClosed()) {
mSocket.close();
}
} catch (IOException ignored) {}
mSocket = null;
mInputBuffer = null;
mOutputBuffer = null;
}
public void updateConnectionStatus(boolean connected) {
if (connected) {
mButtonConnect.setText(R.string.stringDisconnect);
} else {
mButtonConnect.setText(R.string.stringConnect);
}
}
public void ShowAlert(String str) {
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
}
public void initPiece() {
/*
createBitmap(Bitmap source, int x, int y, int width, int height) - Returns an immutable bitmap from the specified subset of the source bitmap.
*/
for (int i = 0; i < 6; i++) {
// белые
arrayOfBitmap[i] = Bitmap.createBitmap(bitmap2, i * 60, 0, 60, 60);
// черные
arrayOfBitmap[i + 6] = Bitmap.createBitmap(bitmap2, i * 60, 60, 60, 60);
}
}
@Override
public void onBackPressed() {
stopReaderThread();
closeSocket();
mButtonConnect.setText(R.string.stringConnect);
mTextViewContent.setText(R.string.waiting_esp);
mEditTextCommand.setText("");
ShowAlert("Выход");
super.onBackPressed(); // это и делает this.finish()
}
@Override
protected void onDestroy() {
stopReaderThread();
closeSocket();
super.onDestroy();
}
public boolean parsingStrFen(String str, Canvas canvas) {
int h = 60; // размер клетки поля
// координаты поля a8
int dx = 26;
int dy = 22;
String s = "";
String s1 = "KQRBNPkqrbnp";
String s2 = "12345678";
// горизонталь
int n = 0;
// вертикаль
int k = 0;
// фигура
int z = -1;
// наличие королей
int king = 0;
// str = str.trim();
/*возвращает индекс в данной строке первого вхождения указанного символа или -1*/
int r = str.indexOf(' ');
// http://proglang.su/java/strings
if (r > 0) {
subStrFen = str.substring(0, r);
int l = subStrFen.length();
for (int i = 0; i < l; i++) {
s = subStrFen.substring(i, i + 1);
if (s.compareTo("/") == 0) {
if (n != 8) {
ShowAlert("ERROR");
}
n = 0;
k++;
continue;
}
if (s2.indexOf(s) >= 0) {
n = n + 1 + s2.indexOf(s);
}
z = s1.indexOf(s);
if (z >= 0) {
switch (z) {
case 0:
{
king++;
break;
}
case 6:
{
king--;
break;
}
}
canvas.drawBitmap(arrayOfBitmap[z], dx + h * n, dy + h * k, paint);
n++;
}
}
}
if (king != 0) {
ShowAlert("ERROR");
}
return true;
}
class DrawView extends View {
public DrawView(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.board);
bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.peice);
//рамка
bitmap4 = Bitmap.createBitmap(bitmap2, 360, 0, 60, 60);
bitmap3 = Bitmap.createBitmap(bitmap1.getWidth(), bitmap1.getHeight(), bitmap1.getConfig());
canvasBmp3 = new Canvas(bitmap3);
//рисуем на канве bitmap3 доску
canvasBmp3.drawBitmap(bitmap1, 0, 0, null);
initPiece();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
// доска
canvas.drawBitmap(bitmap3, 0, 0, paint);
parsingStrFen(StrFen, canvas);
}
public boolean onTouchEvent(MotionEvent event) {
int h = 60; // размер клетки поля
// координаты поля a8
int dx = 26;
int dy = 22;
// номер поля
// a1 - 0 h8 - 63
int NumPol = 0;
// координаты левого угла поля
int XPol, YPol;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
touchX = (int) event.getX();
touchY = (int) event.getY();
// ShowAlert("x="+touchX+" y="+touchY);
XPol = (touchX - dx) / h;
YPol = (touchY - dy) / h;
if (touchX < dx | touchX > dx + 8 * h) {
return true;
}
if (touchY < dy | touchY > dy + 8 * h) {
return true;
}
NumPol = 63-((7-XPol)+8*YPol);
ShowAlert("Поле " + NumPol);
canvasBmp3.drawBitmap(bitmap1, 0, 0, null); canvasBmp3.drawBitmap(bitmap4, dx + h * XPol, dy + h * YPol, null);
//вызываем onDraw
invalidate();
}
return true;
}
}
}

package com.example.touchChess;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class MainActivity extends Activity {
private int h = 60;
private int dx = 26;
private int dy = 22;
private int touchX, touchY;
private int XPol, YPol;
// Выделение
private int selectedX = -1, selectedY = -1;
private boolean hasSelection = false;
// Битмапы и канвасы
private Bitmap[] arrayOfBitmap = new Bitmap[12];
private Bitmap bitmap1, bitmap2, bitmap3, bitmap4, bitmap5;
private Canvas canvasBmp3, canvasBmp5;
private Paint paint;
private String StrFen;
// Сеть
private Socket mSocket;
private InputStream mInputBuffer;
private OutputStream mOutputBuffer;
private Thread mReaderThread;
private volatile boolean mIsReading = false;
private String mServerPort = "8880";
private String mServerAddress = "192.168.4.1";
// UI
private TextView mTextViewContent;
private ScrollView mScrollViewContent;
private Button mButtonConnect;
private Button mButtonSend;
private EditText mEditTextCommand;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrFen = getString(R.string.perft0);
FrameLayout container = findViewById(R.id.boardContainer);
container.addView(new DrawView(this));
mScrollViewContent = findViewById(R.id.scrollViewContent);
mTextViewContent = findViewById(R.id.textViewContent);
mButtonConnect = findViewById(R.id.buttonConnect);
mButtonConnect.requestFocus();
mButtonSend = findViewById(R.id.buttonSend);
mEditTextCommand = findViewById(R.id.editTextCommand);
mButtonConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new ConnectTask().execute();
}
});
mButtonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String cmd = mEditTextCommand.getText().toString().trim();
if (cmd.isEmpty()) {
ShowAlert("Введите команду");
return;
}
new SendTask().execute(cmd);
}
});
}
// --- Сеть ---
private boolean isConnected() {
return mSocket != null && mSocket.isConnected() && !mSocket.isClosed();
}
private class ConnectTask extends AsyncTask<Void, Void, Boolean> {
private String errorMessage = null;
@Override
protected Boolean doInBackground(Void... arg0) {
if (!isConnected()) {
try {
mSocket = new Socket();
mSocket.connect(
new InetSocketAddress(mServerAddress, Integer.parseInt(mServerPort)),
5000
);
mInputBuffer = mSocket.getInputStream();
mOutputBuffer = mSocket.getOutputStream();
startReaderThread();
return true;
} catch (Exception e) {
errorMessage = e.getClass().getName() + ": " +
(e.getMessage() != null ? e.getMessage() : "no message");
return false;
}
} else {
stopReaderThread();
closeSocket();
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
updateConnectionStatus(result);
if (errorMessage != null) ShowAlert(errorMessage);
}
}
private class SendTask extends AsyncTask<String, Void, Boolean> {
private String errorMessage = null;
@Override
protected Boolean doInBackground(String... params) {
if (!isConnected()) {
errorMessage = "Нет соединения";
return false;
}
try {
mOutputBuffer.write((params[0] + "X").getBytes("UTF-8"));
mOutputBuffer.flush();
return true;
} catch (Exception e) {
errorMessage = e.getClass().getName() + ": " +
(e.getMessage() != null ? e.getMessage() : "no message");
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
if (!result && errorMessage != null) ShowAlert(errorMessage);
}
}
private void startReaderThread() {
mIsReading = true;
mReaderThread = new Thread(new Runnable() {
@Override
public void run() {
while (mIsReading && mInputBuffer != null) {
try {
int available = mInputBuffer.available();
if (available > 0) {
byte[] buffer = new byte[available];
int bytesRead = mInputBuffer.read(buffer);
if (bytesRead > 0) {
final String s = new String(buffer, 0, bytesRead, "UTF-8")
.replace("\r", "")
.replaceAll("\n+", "\n");
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mTextViewContent != null) mTextViewContent.append(s);
}
});
mScrollViewContent.post(new Runnable() {
@Override
public void run() {
mScrollViewContent.fullScroll(View.FOCUS_DOWN);
}
});
}
} else {
Thread.sleep(50);
}
} catch (IOException | InterruptedException e) {
break;
}
}
}
});
mReaderThread.start();
}
private void stopReaderThread() {
mIsReading = false;
if (mReaderThread != null) {
mReaderThread.interrupt();
try { mReaderThread.join(1000); } catch (InterruptedException ignored) {}
mReaderThread = null;
}
}
private void closeSocket() {
try {
if (mSocket != null && !mSocket.isClosed()) mSocket.close();
} catch (IOException ignored) {}
mSocket = null;
mInputBuffer = null;
mOutputBuffer = null;
}
private void updateConnectionStatus(boolean connected) {
mButtonConnect.setText(connected ? R.string.stringDisconnect : R.string.stringConnect);
}
// --- Шахматы ---
private void prepareBoard() {
canvasBmp3.drawBitmap(bitmap1, 0, 0, null);
parsingStrFen(StrFen, canvasBmp3);
}
private void clearCell(int cellX, int cellY) {
int x = dx + h * cellX;
int y = dy + h * cellY;
if (x < 0 || y < 0 || x + 60 > bitmap3.getWidth() || y + 60 > bitmap3.getHeight()) return;
canvasBmp3.drawBitmap(bitmap1,
new Rect(x, y, x + 60, y + 60),
new Rect(x, y, x + 60, y + 60), null);
}
private void extractFigure(int cellX, int cellY) {
int srcX = dx + h * cellX;
int srcY = dy + h * cellY;
if (srcX < 0 || srcY < 0 || srcX + 60 > bitmap3.getWidth() || srcY + 60 > bitmap3.getHeight()) return;
canvasBmp5.drawColor(Color.TRANSPARENT);
canvasBmp5.drawBitmap(bitmap3,
new Rect(srcX, srcY, srcX + 60, srcY + 60),
new Rect(0, 0, 60, 60), null);
Bitmap cellMask = Bitmap.createBitmap(bitmap1, srcX, srcY, 60, 60);
int[] pixels = new int[60 * 60];
bitmap5.getPixels(pixels, 0, 60, 0, 0, 60, 60);
int[] maskPixels = new int[60 * 60];
cellMask.getPixels(maskPixels, 0, 60, 0, 0, 60, 60);
for (int i = 0; i < pixels.length; i++) {
if (pixels[i] == maskPixels[i]) pixels[i] = Color.TRANSPARENT;
}
bitmap5.setPixels(pixels, 0, 60, 0, 0, 60, 60);
}
private boolean bitmap5HasContent() {
int[] pixels = new int[60 * 60];
bitmap5.getPixels(pixels, 0, 60, 0, 0, 60, 60);
for (int p : pixels) {
if (p != Color.TRANSPARENT) return true;
}
return false;
}
private void initPiece() {
for (int i = 0; i < 6; i++) {
arrayOfBitmap[i] = Bitmap.createBitmap(bitmap2, i * 60, 0, 60, 60);
arrayOfBitmap[i + 6] = Bitmap.createBitmap(bitmap2, i * 60, 60, 60, 60);
}
}
public boolean parsingStrFen(String str, Canvas canvas) {
String s1 = "KQRBNPkqrbnp";
String s2 = "12345678";
int n = 0, k = 0, king = 0;
int r = str.indexOf(' ');
if (r <= 0) return false;
String sub = str.substring(0, r);
for (int i = 0; i < sub.length(); i++) {
String s = sub.substring(i, i + 1);
if (s.equals("/")) {
if (n != 8) ShowAlert("ERROR");
n = 0; k++; continue;
}
if (s2.indexOf(s) >= 0) n += 1 + s2.indexOf(s);
int z = s1.indexOf(s);
if (z >= 0) {
if (z == 0) king++;
if (z == 6) king--;
canvas.drawBitmap(arrayOfBitmap[z], dx + h * n, dy + h * k, paint);
n++;
}
}
if (king != 0) ShowAlert("ERROR");
return true;
}
private void ShowAlert(String str) {
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
}
@Override
public void onBackPressed() {
stopReaderThread();
closeSocket();
mButtonConnect.setText(R.string.stringConnect);
mTextViewContent.setText(R.string.waiting_esp);
mEditTextCommand.setText("");
ShowAlert("Выход");
super.onBackPressed();
}
@Override
protected void onDestroy() {
stopReaderThread();
closeSocket();
super.onDestroy();
}
// --- Отрисовка ---
class DrawView extends View {
public DrawView(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.board);
bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.peice);
bitmap4 = Bitmap.createBitmap(bitmap2, 360, 0, 60, 60);
bitmap3 = Bitmap.createBitmap(bitmap1.getWidth(), bitmap1.getHeight(), Bitmap.Config.ARGB_8888);
bitmap5 = Bitmap.createBitmap(60, 60, Bitmap.Config.ARGB_8888);
canvasBmp3 = new Canvas(bitmap3);
canvasBmp5 = new Canvas(bitmap5);
initPiece();
prepareBoard();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(80, 102, 204, 255);
canvas.drawBitmap(bitmap3, 0, 0, paint);
if (hasSelection) {
canvas.drawBitmap(bitmap4, dx + h * selectedX, dy + h * selectedY, null);
}
//canvas.drawBitmap(bitmap5, 0, 0, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN) return true;
touchX = (int) event.getX();
touchY = (int) event.getY();
if (touchX < dx || touchX > dx + 8 * h) return true;
if (touchY < dy || touchY > dy + 8 * h) return true;
XPol = (touchX - dx) / h;
YPol = (touchY - dy) / h;
if (!hasSelection) {
// Первый тап — выбор фигуры
extractFigure(XPol, YPol);
if (bitmap5HasContent()) {
selectedX = XPol;
selectedY = YPol;
hasSelection = true;
int num = 63 - ((7 - XPol) + 8 * YPol);
//ShowAlert("Поле " + num);
} else {
ShowAlert("Клетка пуста");
}
} else {
// Второй тап — перемещение
if (XPol == selectedX && YPol == selectedY) {
// Тап по той же клетке — снять выделение
hasSelection = false;
selectedX = -1;
selectedY = -1;
canvasBmp5.drawColor(Color.TRANSPARENT);
ShowAlert("Снято выделение");
} else {
int fromNum = 63 - ((7 - selectedX) + 8 * selectedY);
int toNum = 63 - ((7 - XPol) + 8 * YPol);
clearCell(selectedX, selectedY); // очистить исходную
clearCell(XPol, YPol); // очистить целевую
int dstX = dx + h * XPol;
int dstY = dy + h * YPol;
canvasBmp3.drawBitmap(bitmap5, dstX, dstY, null); // поставить фигуру
canvasBmp5.drawColor(Color.TRANSPARENT);
hasSelection = false;
selectedX = -1;
selectedY = -1;
ShowAlert("Ход: " + fromNum + " → " + toNum);
}
}
invalidate();
return true;
}
}
}
Перейдем к следующему - полученный от тапов ход преобразуем в шахматную нотацию типа e2e4,
только откуда куда, далее вставляем полученный ход в mEditTextCommand и оправляем на сервер mButtonSend.
Далее ждем ответ от сервера, анализируем mTextViewContent и ищем строку типа "mov e2e4 w@". для начала просто покажем это так - public static void showAlert(Context context,String title, String message, View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title);
if (view==null)
{
builder.setMessage(message);
}
else
{
builder.setView(view);
}
builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
}
public static Context getInstance() {
return sInstance;
}
public void ShowAlert(String str) {
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
}
Понял задачу. Нужно:
Перевести ход из номеров клеток в нотацию (e2e4)
Вставить в EditText и отправить
Найти в ответе сервера строку mov e2e4 w@ и показать через AlertDialog
Вот полный код с новыми добавлениями:
Т.к. TextView содержит все предыдущие ходы очистим его вместе с отправкой хода на сервер
или как сам посчитаешь когда лучше очистить TextView, старые ходы нам уже не нужны
Тут есть нюанс: если очищать TextView до того, как поток чтения найдёт строку mov ..., ты можешь потерять тот самый ответ, который ищешь.
Вариант 1 (самый надёжный): очищать только после того, как ответ найден
Это гарантирует, что логика checkServerResponse() успеет увидеть строку mov e2e4 w@.
Меняем только метод checkServerResponse:

Ставлю более сложную задачу:
-У нас реализован:
- Получаем ход от тапов
- Отправляем его на сервер
- Получаем и парсим ответ от сервера
Варианты ответа
1. Если шахматный вижок на сервере принял ход для обработки, сервер вернет наш ход, напр.- mov e2e4 w@
Мы реагируем на это следуюим образом - ни каких алерт не показываем, а автоматически направляем движку
следующую команду - 0 (ноль) таке через mEditTextCommand.
2. Если шахматный движок на сервере не принял ход для обработки (причины могут быть разные -нелегальый ход и т.п.) - в ответе
будет символ #.
Если ход не принят, мы должны вернуть позицию в момент до нелегального хода.
Для этого мы должны держать в памяти bitmap позиции до хода и просто нарисовать ее в ответ на
нелегальный ход.
3.Если ход легальный, то после отправки серверу 0 (ноль)
в его ответе будет содержаться ход, напр.- mov e7e5 b@
Мы должны выполнить это перемещние на нашей bitmap доске (алерты с ходом можно не показывать).
Далее все повторяется,т.е. ход наш.
Задача понятна. Нужен конечный автомат из трёх состояний:
WAITING_CONFIRMATION — ждём ответ на ход пользователя (mov ... w@ = принят, # = отклонён)
WAITING_ENGINE — ждём ход движка (mov ... b@)
IDLE — можно ходить
Плюс бэкап bitmap3 перед ходом для отката при #.
Пользователь тапает e2 → тапает e4
│
├─ Сохраняем bitmapBackup (копия bitmap3 до хода)
├─ Двигаем фигуру на bitmap3
├─ Отправляем "e2e4" на сервер
├─ serverState = WAITING_CONFIRMATION
│
▼
Сервер отвечает "mov e2e4 w@"
│
├─ Очищаем TextView
├─ Отправляем "0"
├─ serverState = WAITING_ENGINE
│
▼
Сервер отвечает "mov e7e5 b@"
│
├─ Очищаем TextView
├─ applyMove("e7e5") — двигаем фигуру движка на bitmap3
├─ invalidate()
├─ serverState = IDLE ← можно ходить снова
│
▼
Если сервер ответил "#"
│
├─ Очищаем TextView
├─ Откат: canvasBmp3.drawBitmap(bitmapBackup, ...)
├─ invalidate()
├─ Toast "Нелегальный ход!"
├─ serverState = IDLE
Работает как задумано)).Есть вопросы к серверу на ESP. Но об этом чть позже
Здорово, что работает! 🎉
С ESP-сервером тоже помогу, когда будешь готов. Там может быть что угодно: от обработки TCP-соединений до протокола общения с шахматным движком. Так что заходи как наладишь железку или когда возникнут вопросы по логике сервера.
А пока — отличный результат, шахматный клиент на Android с сетевым движком и отрисовкой на Canvas, и всё это работает в N-IDE. Не всякий взрослый проект такое может 😊
Что планируешь дальше — допиливать визуал (подсветка возможных ходов, например) или сразу к серверу?