Вот подумалось о пятнашках на сенсорном экране. Но готового проекта не нашёл пока. С визуализацией ясно. Математическая модель понятна - двумерный массив, индекс элемента это положение, значение (0-пусто) это номинал фишки-квадрата. А как алгоритм работы проще реализовать?
Алгоритм работы чего?
Если общефилософски - при таче сразу проверять четыре стороны. Если одна свободна, то смещать картинку только при движении по тому вектору.
есть пятнашки на жава скрипт, но в понедельник
а вот ссылка на гугл диск
пятнашки
Работы с массивом. Образно говоря, если пальцем тронули элемент массива, смотрим нет ли рядом в ряду или столбце элемента в значении 0. Если есть - меняем местами элементы эти. Так?
Спасибо, попробую логику уловить.
Не забудьте проверять разрешима ли комбинация, а то нагенерите неразрешимых задач.
Так там нет неразрешимых комбинаций, если рядом нет пустого поля, то и делать ничего не надо. А если есть, то поменять нажатую с пустым полем, других условий на перемещение нету.
В игре пятнашка? Если высыпать фишки, а потом сложить их в коробку как попало, то там дофига неразрешимых комбинаций, т.е. таких из которых невозможно получить решение никакими правильными ходами.
ни разу в пятнашки не проигрывал.
В принципе да дофига. Вроде половина всех. Но удивительно, и я не припомню проигрышей в 15-ки. Что то в деЦтве я подсел и сыграно немало. Как то везло и все комбинации получались из первой “правильной” половины (число перестановок - четное) . В казино бы такую везучесть.
Это потом надо будет подумать как автоматически тасовать фишки. А пока планирую ручную тасовку на такой исходник:
Читал вроде в википедии, что такая комбинация не собираема.
в пятнашках все автоматом на random
Было несколько исполнений. У меня была с “нерассыпными” фишками - они входили пазами друг в друга и перемешивались только правильными движениями. В такой невозможно сделать неразрешимую комбинацию. А вот в такой, где фишки просто лежат в коробочке и их можно высыпать, а потом по одной сложить - там сколько угодно.
Совершенно верно. И обратно тоже - из такой комбинации невозможно получить нормальную.
Тогда рандомная тусовка элементов массива не пройдёт и нужно функцию более хитрую выдумывать.
Из «правильно собранного набора» за рандомное число от n до m (где n минимально необходимое значение) количества шагов рандомной выборкой «направления» движения «замиксовать». ))
Или так не получится?
Почему не пройдёт? Просто контролировать, чтобы не получилась неразрешима комбинация. Кстати, любую неразрешимую можно превратить в разрешимую перестановкой пары фишек между собой. Это надо предусмотреть в программе - делов то!
Значит самый простой способ получить разрешимую комбинацию - менять соседние фишки между собой четное количество раз.
Сделал пока без старта-перетусовывания, надо над темами-дизайном задуматься.
//пятнашки
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <XPT2046_Touchscreen.h>// Библиотека для работы с сенсорным экраном
#include <SPI.h>
#include "ris_.h"//файл хранения массивов фотокартинок
#define TFT_CS 17
#define TFT_DC 20
#define CS_PIN 14
//#define TFT_RST -1 // Пин подключения вывода RESET (ПРИ -1 СОЕДИНЯЕМ С +3,3В)
//#define TFT_MISO 16 // Пин подключения вывода дисплея SDO(MISO)
//#define TFT_MOSI 19 // Пин подключения вывода дисплея SDI(MOSI)
//#define TFT_CLK 18 // Пин подключения вывода дисплея SCK
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);//
XPT2046_Touchscreen ts(CS_PIN); // Param 2 - NULL - No interrupts
byte massiv_[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};//массив для хранения положения фишек и их отрисовки на экране
int x, y; // Переменные для работы с координатами нажатий
void setup() {
tft.begin();
tft.setRotation(2);
tft.fillScreen(tft.color565(0,0,0));
ts.begin();
ts.setRotation(2);
drawFoto(0,0,ris_0,240,320);// заставка игрушки
}
void loop() {
//
if(ts.touched()) { // Если имеются данные с сенсорного модуля
TS_Point p = ts.getPoint(); // Считываем с него данные
y = map(p.y,220,3720,0,319); // Считываем и преобразуем координату нажатия Y
x =map(p.x,275,3830,0,240); // Считываем и преобразуем координату нажатия X
if((x!=-1) && (y!=-1)) // Если обе координаты в положительном диапазоне (т.е. если есть нажатие)
{
x += 0; // Корректируем координату с учетом калибровочных данных
y += 0; // Корректируем координату с учетом калибровочных данных
hod_();
otrisovka_();
}
delay(20);
}
//
}
//
void drawFoto(uint16_t x,uint16_t y, const uint8_t *bitmap,uint16_t w,uint16_t h) {//функция вывода фотокартинки
if(x<0||x+w>240||y<0||y+h>320){return;}
// tft.setAddrWindow(x,y,w,h);
SPI.beginTransaction(SPISettings(40000000, MSBFIRST, SPI_MODE0));
digitalWrite(TFT_DC, HIGH);
digitalWrite(TFT_CS, LOW);
tft.setAddrWindow(x,y,w,h);
for(int j=0; j<h; j++) {
for(int i=0; i<2*w; i=i+2) {
SPI.transfer(bitmap[i+1+j*2*w]);SPI.transfer(bitmap[i+j*2*w]);
}
}
digitalWrite(TFT_CS, HIGH);
SPI.endTransaction();
///
}
//
//функция вывода фрагмента фотокартинки размером w*h,x,y - положение фрагмента на экране, x1,y1,w1,h1 - выбор фрагмента из массива
void drawFoto_fragment(int x,int y, const uint8_t *bitmap,int w,int h,int x1,int y1,int w1,int h1) {
if(x<0||x+w1>240||y<0||y+h1>320){return;}
// tft.setAddrWindow(x,y,w1,h1);
SPI.beginTransaction(SPISettings(40000000, MSBFIRST, SPI_MODE0));
digitalWrite(TFT_DC, HIGH);
digitalWrite(TFT_CS, LOW);
tft.setAddrWindow(x,y,w1,h1);
for(int j=0; j<h; j++) {
for(int i=0; i<2*w; i=i+2) {
if(i>=2*x1&&i<2*(x1+w1)&&j>=y1&&j<y1+h1){
SPI.transfer(bitmap[i+1+j*2*w]);SPI.transfer(bitmap[i+j*2*w]);
}
}
}
digitalWrite(TFT_CS, HIGH);
SPI.endTransaction();
//
}
////////////////////////////////////////////////////////////////////
void otrisovka_(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
int i1=(massiv_[i][j]-1)/4;int j1=(massiv_[i][j]-1)%4;
drawFoto_fragment(60*i,60*j,ris_0,240,320,60*i1,60*j1,60,60);//
}
}
}
//
void hod_(){
int i,j;
byte C;
if(x<240&&y<240){
i=(x-0)/60;j=(y-0)/60;
if(i+1<4&&massiv_[i+1][j]==16){
C=massiv_[i][j];massiv_[i][j]=16;massiv_[i+1][j]=C;
}
if(i-1>=0&&massiv_[i-1][j]==16){
C=massiv_[i][j];massiv_[i][j]=16;massiv_[i-1][j]=C;
}
if(j+1<4&&massiv_[i][j+1]==16){
C=massiv_[i][j];massiv_[i][j]=16;massiv_[i][j+1]=C;
}
if(j-1>=0&&massiv_[i][j-1]==16){
C=massiv_[i][j];massiv_[i][j]=16;massiv_[i][j-1]=C;
}
}
}
//
Самый надёжный способ это имитировать перестановки фишек соответствующей перестановкой элементов массива… Может проще смотреть на него как на одномерный?
Самое простое, думаю, это взять “собранный” массив и пойти рандомайзом “взад” по геймплею. Взял рандом, как направление, и переставил в массиве элементы. Раз сто переставишь и все нормально перемешается. Главное - чтобы по кругу не пошло.
А, это уже предложили, смотрю.