Compare commits
3
Commits
33de92f4ce
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a67d6d4e7b | ||
|
|
f6d29f1fb9 | ||
|
|
c66a4cc828 |
Generated
+8
@@ -4,6 +4,14 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DropdownSelection timestamp="2025-05-17T08:55:13.914480200Z">
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=28161JEGR06778" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ android {
|
|||||||
versionName = "1.0"
|
versionName = "1.0"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -35,7 +37,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation(libs.appcompat)
|
implementation(libs.appcompat)
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
implementation(libs.constraintlayout)
|
implementation(libs.constraintlayout)
|
||||||
@@ -43,6 +44,11 @@ dependencies {
|
|||||||
implementation(libs.lifecycle.viewmodel.ktx)
|
implementation(libs.lifecycle.viewmodel.ktx)
|
||||||
implementation(libs.navigation.fragment)
|
implementation(libs.navigation.fragment)
|
||||||
implementation(libs.navigation.ui)
|
implementation(libs.navigation.ui)
|
||||||
|
|
||||||
|
implementation("androidx.room:room-runtime:2.7.1")
|
||||||
|
implementation(libs.room.common.jvm)
|
||||||
|
annotationProcessor("androidx.room:room-compiler:2.7.1")
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.room.Database;
|
||||||
|
import androidx.room.Room;
|
||||||
|
import androidx.room.RoomDatabase;
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = {LevelRecord.class},
|
||||||
|
version = 1,
|
||||||
|
exportSchema = true
|
||||||
|
)
|
||||||
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
|
public abstract LevelRecordDao levelRecordDao();
|
||||||
|
|
||||||
|
private static volatile AppDatabase INSTANCE;
|
||||||
|
|
||||||
|
public static AppDatabase getDatabase(Context context) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (AppDatabase.class) {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
|
||||||
|
AppDatabase.class, "memory-db")
|
||||||
|
.fallbackToDestructiveMigration()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GameRepository {
|
||||||
|
private final LevelRecordDao recordDao;
|
||||||
|
|
||||||
|
public GameRepository(LevelRecordDao recordDao) {
|
||||||
|
this.recordDao = recordDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сохранить результат уровня
|
||||||
|
public void saveLevelResult(int levelId, int score) {
|
||||||
|
new Thread(() -> {
|
||||||
|
LevelRecord existing = recordDao.getRecordForLevel(levelId);
|
||||||
|
|
||||||
|
if (existing == null) {
|
||||||
|
// Первая попытка на этом уровне
|
||||||
|
recordDao.insert(new LevelRecord(levelId, score, 1));
|
||||||
|
} else {
|
||||||
|
// Обновляем если результат лучше
|
||||||
|
recordDao.updateIfBetter(levelId, score);
|
||||||
|
if (score <= existing.bestScore) {
|
||||||
|
// Просто увеличиваем счётчик попыток
|
||||||
|
existing.attemptsCount++;
|
||||||
|
recordDao.update(existing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получить все записи
|
||||||
|
public LiveData<List<LevelRecord>> getAllRecords() {
|
||||||
|
MutableLiveData<List<LevelRecord>> liveData = new MutableLiveData<>();
|
||||||
|
new Thread(() -> {
|
||||||
|
liveData.postValue(recordDao.getAllRecords());
|
||||||
|
}).start();
|
||||||
|
return liveData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сбросить все данные
|
||||||
|
public void resetAllData() {
|
||||||
|
new Thread(() -> {
|
||||||
|
recordDao.deleteAllRecords();
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
@Entity(tableName = "level_records")
|
||||||
|
public class LevelRecord {
|
||||||
|
@PrimaryKey
|
||||||
|
public int levelId;
|
||||||
|
|
||||||
|
public int bestScore;
|
||||||
|
public int attemptsCount;
|
||||||
|
public long lastPlayedTime;
|
||||||
|
|
||||||
|
public LevelRecord(int levelId, int bestScore, int attemptsCount) {
|
||||||
|
this.levelId = levelId;
|
||||||
|
this.bestScore = bestScore;
|
||||||
|
this.attemptsCount = attemptsCount;
|
||||||
|
this.lastPlayedTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.Update;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
public interface LevelRecordDao {
|
||||||
|
@Insert
|
||||||
|
void insert(LevelRecord record);
|
||||||
|
|
||||||
|
@Update
|
||||||
|
void update(LevelRecord record);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM level_records WHERE levelId = :levelId")
|
||||||
|
LevelRecord getRecordForLevel(int levelId);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM level_records ORDER BY levelId ASC")
|
||||||
|
List<LevelRecord> getAllRecords();
|
||||||
|
|
||||||
|
@Query("DELETE FROM level_records")
|
||||||
|
void deleteAllRecords();
|
||||||
|
|
||||||
|
@Query("UPDATE level_records SET bestScore = :newScore, attemptsCount = attemptsCount + 1 WHERE levelId = :levelId AND :newScore > bestScore")
|
||||||
|
void updateIfBetter(int levelId, int newScore);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,36 +10,80 @@ import androidx.navigation.NavController;
|
|||||||
import androidx.navigation.Navigation;
|
import androidx.navigation.Navigation;
|
||||||
import androidx.navigation.ui.AppBarConfiguration;
|
import androidx.navigation.ui.AppBarConfiguration;
|
||||||
import androidx.navigation.ui.NavigationUI;
|
import androidx.navigation.ui.NavigationUI;
|
||||||
|
import androidx.room.Room;
|
||||||
|
|
||||||
import com.kolobochki.memory.databinding.ActivityMainBinding;
|
import com.kolobochki.memory.databinding.ActivityMainBinding;
|
||||||
|
|
||||||
|
import com.kolobochki.memory.AppDatabase;
|
||||||
|
import com.kolobochki.memory.GameRepository;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private ActivityMainBinding binding;
|
private ActivityMainBinding binding;
|
||||||
private NavController navController;
|
private NavController navController;
|
||||||
|
|
||||||
|
private GameRepository gameRepository;
|
||||||
|
private static AppDatabase database;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
database = Room.databaseBuilder(getApplicationContext(),
|
||||||
|
AppDatabase.class, "memory-db")
|
||||||
|
.fallbackToDestructiveMigration()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
gameRepository = new GameRepository(database.levelRecordDao());
|
||||||
|
|
||||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
|
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
|
||||||
|
|
||||||
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
|
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
|
||||||
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_task1)
|
R.id.navigation_home,
|
||||||
|
R.id.navigation_dashboard,
|
||||||
|
R.id.navigation_task1,
|
||||||
|
R.id.navigation_task2,
|
||||||
|
R.id.navigation_task3,
|
||||||
|
R.id.navigation_task4,
|
||||||
|
R.id.navigation_info,
|
||||||
|
R.id.navigation_records)
|
||||||
.build();
|
.build();
|
||||||
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
||||||
NavigationUI.setupWithNavController(binding.navView, navController);
|
NavigationUI.setupWithNavController(binding.navView, navController);
|
||||||
|
|
||||||
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
||||||
if (destination.getId() == R.id.navigation_task1) {
|
if (destination.getId() == R.id.navigation_task1
|
||||||
|
|| destination.getId() == R.id.navigation_task2
|
||||||
|
|| destination.getId() == R.id.navigation_task3
|
||||||
|
|| destination.getId() == R.id.navigation_task4
|
||||||
|
|| destination.getId() == R.id.navigation_info
|
||||||
|
|| destination.getId() == R.id.navigation_records) {
|
||||||
binding.navView.setVisibility(View.GONE);
|
binding.navView.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
binding.navView.setVisibility(View.VISIBLE);
|
binding.navView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameRepository getGameRepository() {
|
||||||
|
return gameRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AppDatabase getDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
if (database != null && database.isOpen()) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.activity.OnBackPressedCallback;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import com.kolobochki.memory.R;
|
||||||
|
import com.kolobochki.memory.databinding.FragmentDashboardBinding;
|
||||||
|
import com.kolobochki.memory.databinding.FragmentInfoBinding;
|
||||||
|
|
||||||
|
public class fragment_info extends Fragment {
|
||||||
|
|
||||||
|
private FragmentInfoBinding binding;
|
||||||
|
private static final String ARG_PARAM1 = "param1";
|
||||||
|
private static final String ARG_PARAM2 = "param2";
|
||||||
|
|
||||||
|
private TextView helpText;
|
||||||
|
|
||||||
|
private String mParam1;
|
||||||
|
private String mParam2;
|
||||||
|
private OnBackPressedCallback backPressedCallback;
|
||||||
|
private String previousTitle;
|
||||||
|
|
||||||
|
public fragment_info() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
public static fragment_info newInstance(String param1, String param2) {
|
||||||
|
fragment_info fragment = new fragment_info();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_PARAM1, param1);
|
||||||
|
args.putString(ARG_PARAM2, param2);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (getArguments() != null) {
|
||||||
|
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||||
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setTitle("Инструкция");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
binding = com.kolobochki.memory.databinding.FragmentInfoBinding .inflate(inflater, container, false);
|
||||||
|
View root = binding.getRoot();
|
||||||
|
|
||||||
|
String instructions =
|
||||||
|
"1. Найти пары:\n" +
|
||||||
|
" - На экране карточки перевернуты рубашкой вверх\n" +
|
||||||
|
" - Открывайте по две карточки, чтобы найти пары\n" +
|
||||||
|
" - Совпавшие карточки остаются открытыми\n" +
|
||||||
|
" - Цель: открыть все пары за минимальное время\n\n" +
|
||||||
|
|
||||||
|
"2. Саймон говорит:\n" +
|
||||||
|
" - Саймон показывает последовательность цветов\n" +
|
||||||
|
" - Повторите показанную последовательность\n" +
|
||||||
|
" - С каждым уровнем последовательность удлиняется\n" +
|
||||||
|
" - Ошибка завершает игру\n\n" +
|
||||||
|
|
||||||
|
"3. Числовая матрица:\n" +
|
||||||
|
" - Запомните расположение чисел в матрице\n" +
|
||||||
|
" - Восстановите числа после их исчезновения\n" +
|
||||||
|
" - Сложность повышается с каждым уровнем\n\n" +
|
||||||
|
|
||||||
|
"4. Найти лишнее:\n" +
|
||||||
|
" - Среди нескольких объектов найдите отличающийся\n" +
|
||||||
|
" - Выберите лишний объект\n" +
|
||||||
|
" - Время на ответ ограничено";
|
||||||
|
|
||||||
|
binding.textView.setText(instructions);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void navigateHome() {
|
||||||
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
|
navController.popBackStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (backPressedCallback != null) {
|
||||||
|
backPressedCallback.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null && previousTitle != null) {
|
||||||
|
actionBar.setTitle(previousTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.OnBackPressedCallback;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.kolobochki.memory.AppDatabase;
|
||||||
|
import com.kolobochki.memory.LevelRecord;
|
||||||
|
import com.kolobochki.memory.LevelRecordDao;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class fragment_records extends Fragment {
|
||||||
|
|
||||||
|
private RecyclerView recyclerView;
|
||||||
|
private StatsAdapter adapter;
|
||||||
|
private LevelRecordDao levelRecordDao;
|
||||||
|
private Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
private OnBackPressedCallback backPressedCallback;
|
||||||
|
private String previousTitle;
|
||||||
|
|
||||||
|
// Названия уровней
|
||||||
|
private final String[] levelNames = {
|
||||||
|
"Найти пары",
|
||||||
|
"Саймон говорит",
|
||||||
|
"Числовая матрица",
|
||||||
|
"Найти лишнее"
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Инициализация базы данных
|
||||||
|
AppDatabase db = AppDatabase.getDatabase(requireContext().getApplicationContext());
|
||||||
|
levelRecordDao = db.levelRecordDao();
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setTitle("Мой прогресс");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_records, container, false);
|
||||||
|
|
||||||
|
recyclerView = view.findViewById(R.id.stats_recycler);
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|
||||||
|
adapter = new StatsAdapter();
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
loadStats();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadStats() {
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
List<LevelRecord> records = levelRecordDao.getAllRecords();
|
||||||
|
|
||||||
|
// Если записей нет - создаем пустые
|
||||||
|
if (records == null || records.isEmpty()) {
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
LevelRecord record = new LevelRecord(i, 0, 0);
|
||||||
|
levelRecordDao.insert(record);
|
||||||
|
}
|
||||||
|
records = levelRecordDao.getAllRecords();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LevelRecord> finalRecords = records;
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setRecords(finalRecords);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
requireActivity().runOnUiThread(() ->
|
||||||
|
Toast.makeText(requireContext(), "Ошибка загрузки данных", Toast.LENGTH_SHORT).show()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Адаптер для RecyclerView
|
||||||
|
private class StatsAdapter extends RecyclerView.Adapter<StatsAdapter.StatsViewHolder> {
|
||||||
|
|
||||||
|
private List<LevelRecord> records;
|
||||||
|
|
||||||
|
public void setRecords(List<LevelRecord> records) {
|
||||||
|
this.records = records;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public StatsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_level_stat, parent, false);
|
||||||
|
return new StatsViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull StatsViewHolder holder, int position) {
|
||||||
|
LevelRecord record = records.get(position);
|
||||||
|
holder.levelName.setText(levelNames[record.levelId - 1]);
|
||||||
|
holder.bestScore.setText("Рекорд: " + record.bestScore);
|
||||||
|
holder.attempts.setText("Попыток: " + record.attemptsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return records != null ? records.size() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StatsViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView levelName, bestScore, attempts;
|
||||||
|
|
||||||
|
StatsViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
levelName = itemView.findViewById(R.id.level_name);
|
||||||
|
bestScore = itemView.findViewById(R.id.best_score);
|
||||||
|
attempts = itemView.findViewById(R.id.attempts_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
package com.kolobochki.memory;
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -14,17 +12,23 @@ import android.widget.ImageView;
|
|||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
import androidx.activity.OnBackPressedCallback;
|
import androidx.activity.OnBackPressedCallback;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.Navigation;
|
import androidx.navigation.Navigation;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.room.Room;
|
||||||
|
|
||||||
|
import com.kolobochki.memory.AppDatabase;
|
||||||
|
import com.kolobochki.memory.LevelRecord;
|
||||||
|
import com.kolobochki.memory.LevelRecordDao;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
import com.kolobochki.memory.R;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class fragment_task1 extends Fragment {
|
public class fragment_task1 extends Fragment {
|
||||||
|
|
||||||
@@ -35,44 +39,35 @@ public class fragment_task1 extends Fragment {
|
|||||||
private OnBackPressedCallback backPressedCallback;
|
private OnBackPressedCallback backPressedCallback;
|
||||||
private String previousTitle;
|
private String previousTitle;
|
||||||
|
|
||||||
// ----------------------------------------------
|
// Game constants
|
||||||
|
private static final int PAIRS_COUNT = 6;
|
||||||
private static final int PAIRS_COUNT = 6; // Кол-во пар
|
private static final int GRID_COLUMNS = 4;
|
||||||
private static final int GRID_COLUMNS = 4; // Кол-во колонок
|
private static final int PREVIEW_TIME = 5000;
|
||||||
private static final int PREVIEW_TIME = 5000; // Задержка в начале в мс
|
private static final int SUCCESS_DELAY = 4000;
|
||||||
private static final int SUCCESS_DELAY = 4000; // Задержка в конце в мс
|
private static final int INITIAL_LIVES = 3;
|
||||||
private static final int INITIAL_LIVES = 3; // Кол-во жизек
|
private static final int LEVEL_ID = 1; // ID для первого уровня
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
|
// Game variables
|
||||||
private int score = 0;
|
private int score = 0;
|
||||||
private int lives = INITIAL_LIVES;
|
private int lives = INITIAL_LIVES;
|
||||||
private int flippedCount = 0;
|
|
||||||
private ImageView firstFlipped = null;
|
private ImageView firstFlipped = null;
|
||||||
private boolean isPreview = true;
|
private boolean isPreview = true;
|
||||||
private boolean isGameComplete = false;
|
private boolean isGameComplete = false;
|
||||||
|
|
||||||
// ----------------------------------------------
|
// Views
|
||||||
|
|
||||||
private GridLayout gridLayout;
|
private GridLayout gridLayout;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private List<Integer> tileImages = new ArrayList<>();
|
private List<Integer> tileImages = new ArrayList<>();
|
||||||
private List<ImageView> tiles = new ArrayList<>();
|
private List<ImageView> tiles = new ArrayList<>();
|
||||||
private LinearLayout livesLayout;
|
private LinearLayout livesLayout;
|
||||||
|
|
||||||
// -----------------------------------------------
|
// Database
|
||||||
|
private AppDatabase database;
|
||||||
|
private LevelRecordDao levelRecordDao;
|
||||||
|
private Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
public fragment_task1() {}
|
public fragment_task1() {}
|
||||||
|
|
||||||
public static fragment_task1 newInstance(String param1, String param2) {
|
|
||||||
fragment_task1 fragment = new fragment_task1();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(ARG_PARAM1, param1);
|
|
||||||
args.putString(ARG_PARAM2, param2);
|
|
||||||
fragment.setArguments(args);
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -81,7 +76,10 @@ public class fragment_task1 extends Fragment {
|
|||||||
mParam2 = getArguments().getString(ARG_PARAM2);
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(true) {
|
database = AppDatabase.getDatabase(requireContext());
|
||||||
|
levelRecordDao = database.levelRecordDao();
|
||||||
|
|
||||||
|
backPressedCallback = new OnBackPressedCallback(true) {
|
||||||
@Override
|
@Override
|
||||||
public void handleOnBackPressed() {
|
public void handleOnBackPressed() {
|
||||||
if (!isGameComplete) {
|
if (!isGameComplete) {
|
||||||
@@ -168,7 +166,6 @@ public class fragment_task1 extends Fragment {
|
|||||||
}, PREVIEW_TIME);
|
}, PREVIEW_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void flipAllTiles() {
|
private void flipAllTiles() {
|
||||||
for (ImageView tile : tiles) {
|
for (ImageView tile : tiles) {
|
||||||
tile.setImageResource(R.drawable.tile_back);
|
tile.setImageResource(R.drawable.tile_back);
|
||||||
@@ -233,11 +230,13 @@ public class fragment_task1 extends Fragment {
|
|||||||
|
|
||||||
private void gameComplete() {
|
private void gameComplete() {
|
||||||
isGameComplete = true;
|
isGameComplete = true;
|
||||||
|
saveGameResult(true);
|
||||||
new Handler().postDelayed(this::navigateHome, 1500);
|
new Handler().postDelayed(this::navigateHome, 1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gameOver() {
|
private void gameOver() {
|
||||||
isGameComplete = true;
|
isGameComplete = true;
|
||||||
|
saveGameResult(false);
|
||||||
new AlertDialog.Builder(requireContext())
|
new AlertDialog.Builder(requireContext())
|
||||||
.setTitle("Игра окончена")
|
.setTitle("Игра окончена")
|
||||||
.setMessage("Вы проиграли. Попробуйте еще раз!")
|
.setMessage("Вы проиграли. Попробуйте еще раз!")
|
||||||
@@ -246,6 +245,49 @@ public class fragment_task1 extends Fragment {
|
|||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveGameResult(boolean isWin) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
LevelRecord existingRecord = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
|
||||||
|
if (existingRecord == null) {
|
||||||
|
// Первая запись для этого уровня
|
||||||
|
LevelRecord newRecord = new LevelRecord(LEVEL_ID, isWin ? score : 0, 1);
|
||||||
|
levelRecordDao.insert(newRecord);
|
||||||
|
|
||||||
|
if (isWin) {
|
||||||
|
showNewRecordToast(score);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
boolean isNewRecord = false;
|
||||||
|
|
||||||
|
if (isWin && score > existingRecord.bestScore) {
|
||||||
|
existingRecord.bestScore = score;
|
||||||
|
isNewRecord = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
existingRecord.attemptsCount++;
|
||||||
|
levelRecordDao.update(existingRecord);
|
||||||
|
|
||||||
|
if (isNewRecord) {
|
||||||
|
showNewRecordToast(score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
requireActivity().runOnUiThread(() ->
|
||||||
|
Toast.makeText(requireContext(), "Ошибка сохранения: " + e.getMessage(), Toast.LENGTH_SHORT).show()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNewRecordToast(int score) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
"Новый рекорд: " + score, Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void navigateHome() {
|
private void navigateHome() {
|
||||||
NavController navController = Navigation.findNavController(requireView());
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
navController.popBackStack();
|
navController.popBackStack();
|
||||||
@@ -257,6 +299,9 @@ public class fragment_task1 extends Fragment {
|
|||||||
if (backPressedCallback != null) {
|
if (backPressedCallback != null) {
|
||||||
backPressedCallback.remove();
|
backPressedCallback.remove();
|
||||||
}
|
}
|
||||||
|
if (database != null) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showExitConfirmationDialog() {
|
private void showExitConfirmationDialog() {
|
||||||
|
|||||||
@@ -0,0 +1,370 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import static com.kolobochki.memory.R.*;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import androidx.activity.OnBackPressedCallback;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.GridLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import com.kolobochki.memory.AppDatabase;
|
||||||
|
import com.kolobochki.memory.LevelRecord;
|
||||||
|
import com.kolobochki.memory.LevelRecordDao;
|
||||||
|
|
||||||
|
public class fragment_task2 extends Fragment {
|
||||||
|
|
||||||
|
private static final String ARG_PARAM1 = "param1";
|
||||||
|
private static final String ARG_PARAM2 = "param2";
|
||||||
|
private static final int LEVEL_ID = 2; // ID для второго уровня
|
||||||
|
|
||||||
|
private String mParam1;
|
||||||
|
private String mParam2;
|
||||||
|
private String previousTitle;
|
||||||
|
private boolean isGameComplete = false;
|
||||||
|
|
||||||
|
private List<Integer> sequence = new ArrayList<>();
|
||||||
|
private int currentStep = 0;
|
||||||
|
private int round = 1;
|
||||||
|
private int lives = 3;
|
||||||
|
private boolean isShowingSequence = false;
|
||||||
|
private boolean isWaitingForInput = false;
|
||||||
|
|
||||||
|
private Button redButton, greenButton, blueButton, yellowButton;
|
||||||
|
private ImageView centerImage;
|
||||||
|
private TextView roundText, livesText;
|
||||||
|
private GridLayout buttonsGrid;
|
||||||
|
|
||||||
|
// Database
|
||||||
|
private AppDatabase database;
|
||||||
|
private LevelRecordDao levelRecordDao;
|
||||||
|
private Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
private final int[] colorImages = {
|
||||||
|
R.drawable.simon_red,
|
||||||
|
R.drawable.simon_green,
|
||||||
|
R.drawable.simon_blue,
|
||||||
|
R.drawable.simon_yellow,
|
||||||
|
R.drawable.simon_off
|
||||||
|
};
|
||||||
|
|
||||||
|
public fragment_task2() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (getArguments() != null) {
|
||||||
|
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||||
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
|
}
|
||||||
|
|
||||||
|
database = AppDatabase.getDatabase(requireContext());
|
||||||
|
levelRecordDao = database.levelRecordDao();
|
||||||
|
|
||||||
|
OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(true) {
|
||||||
|
@Override
|
||||||
|
public void handleOnBackPressed() {
|
||||||
|
if (!isGameComplete) {
|
||||||
|
showExitConfirmationDialog();
|
||||||
|
} else {
|
||||||
|
setEnabled(false);
|
||||||
|
navigateHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
requireActivity().getOnBackPressedDispatcher().addCallback(this, backPressedCallback);
|
||||||
|
|
||||||
|
executor.execute(() -> {
|
||||||
|
LevelRecord existingRecord = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
if (existingRecord != null) {
|
||||||
|
existingRecord.attemptsCount++;
|
||||||
|
levelRecordDao.update(existingRecord);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setTitle("Упражнение 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_task2, container, false);
|
||||||
|
|
||||||
|
redButton = view.findViewById(R.id.redButton);
|
||||||
|
greenButton = view.findViewById(R.id.greenButton);
|
||||||
|
blueButton = view.findViewById(R.id.blueButton);
|
||||||
|
yellowButton = view.findViewById(R.id.yellowButton);
|
||||||
|
centerImage = view.findViewById(R.id.centerImage);
|
||||||
|
roundText = view.findViewById(R.id.roundText);
|
||||||
|
livesText = view.findViewById(R.id.livesText);
|
||||||
|
buttonsGrid = view.findViewById(R.id.buttonsGrid);
|
||||||
|
|
||||||
|
redButton.setOnClickListener(v -> onColorClicked(0));
|
||||||
|
greenButton.setOnClickListener(v -> onColorClicked(1));
|
||||||
|
blueButton.setOnClickListener(v -> onColorClicked(2));
|
||||||
|
yellowButton.setOnClickListener(v -> onColorClicked(3));
|
||||||
|
|
||||||
|
startNewGame();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startNewGame() {
|
||||||
|
sequence.clear();
|
||||||
|
round = 1;
|
||||||
|
lives = 3;
|
||||||
|
currentStep = 0;
|
||||||
|
isGameComplete = false;
|
||||||
|
updateUI();
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
generateNextSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
showSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateNextSequence() {
|
||||||
|
Random random = new Random();
|
||||||
|
sequence.add(random.nextInt(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSequence() {
|
||||||
|
isShowingSequence = true;
|
||||||
|
isWaitingForInput = false;
|
||||||
|
buttonsGrid.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
|
Handler handler = new Handler();
|
||||||
|
for (int i = 0; i < sequence.size(); i++) {
|
||||||
|
final int colorIndex = sequence.get(i);
|
||||||
|
handler.postDelayed(() -> showColor(colorIndex), i * 1000L);
|
||||||
|
handler.postDelayed(() -> resetCenterImage(), i * 1000L + 800L);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.postDelayed(() -> {
|
||||||
|
isShowingSequence = false;
|
||||||
|
isWaitingForInput = true;
|
||||||
|
currentStep = 0;
|
||||||
|
buttonsGrid.setVisibility(View.VISIBLE);
|
||||||
|
centerImage.setImageResource(R.drawable.simon_off);
|
||||||
|
}, sequence.size() * 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void highlightButton(int colorIndex) {
|
||||||
|
switch (colorIndex) {
|
||||||
|
case 0:
|
||||||
|
redButton.setBackgroundResource(R.drawable.simon_red);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
greenButton.setBackgroundResource(R.drawable.simon_green);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
blueButton.setBackgroundResource(R.drawable.simon_blue);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
yellowButton.setBackgroundResource(R.drawable.simon_yellow);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showColor(int colorIndex) {
|
||||||
|
centerImage.setImageResource(colorImages[colorIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetCenterImage() {
|
||||||
|
centerImage.setImageResource(R.drawable.simon_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetButtons() {
|
||||||
|
redButton.setBackgroundResource(R.drawable.simon_off);
|
||||||
|
greenButton.setBackgroundResource(R.drawable.simon_off);
|
||||||
|
blueButton.setBackgroundResource(R.drawable.simon_off);
|
||||||
|
yellowButton.setBackgroundResource(R.drawable.simon_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onColorClicked(int colorIndex) {
|
||||||
|
if (!isWaitingForInput || isShowingSequence) return;
|
||||||
|
|
||||||
|
showColor(colorIndex);
|
||||||
|
new Handler().postDelayed(this::resetCenterImage, 300);
|
||||||
|
|
||||||
|
if (colorIndex == sequence.get(currentStep)) {
|
||||||
|
currentStep++;
|
||||||
|
if (currentStep == sequence.size()) {
|
||||||
|
round++;
|
||||||
|
currentStep = 0;
|
||||||
|
updateUI();
|
||||||
|
|
||||||
|
checkAndUpdateRecord(round);
|
||||||
|
|
||||||
|
generateNextSequence();
|
||||||
|
new Handler().postDelayed(() -> {
|
||||||
|
if (!isGameComplete) {
|
||||||
|
showSequence();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lives--;
|
||||||
|
updateUI();
|
||||||
|
if (lives <= 0) {
|
||||||
|
gameOver();
|
||||||
|
} else {
|
||||||
|
new Handler().postDelayed(() -> {
|
||||||
|
if (!isGameComplete) {
|
||||||
|
currentStep = 0;
|
||||||
|
showSequence();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAndUpdateRecord(int currentRound) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
LevelRecord record = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
if (record != null && currentRound > record.bestScore) {
|
||||||
|
record.bestScore = currentRound;
|
||||||
|
levelRecordDao.update(record);
|
||||||
|
showNewRecordToast(currentRound);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUI() {
|
||||||
|
roundText.setText("Раунд: " + round);
|
||||||
|
|
||||||
|
StringBuilder hearts = new StringBuilder();
|
||||||
|
for (int i = 0; i < lives; i++) {
|
||||||
|
hearts.append("❤️");
|
||||||
|
}
|
||||||
|
livesText.setText(hearts.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gameOver() {
|
||||||
|
isGameComplete = true;
|
||||||
|
isWaitingForInput = false;
|
||||||
|
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Игра окончена")
|
||||||
|
.setMessage("Вы прошли " + round + " раундов!")
|
||||||
|
.setPositiveButton("Играть снова", (dialog, which) -> {
|
||||||
|
isGameComplete = false;
|
||||||
|
startNewGame();
|
||||||
|
})
|
||||||
|
.setNegativeButton("Выход", (dialog, which) -> navigateHome())
|
||||||
|
.setCancelable(false)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveGameResult(int roundsCompleted) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
LevelRecord existingRecord = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
|
||||||
|
if (existingRecord == null) {
|
||||||
|
LevelRecord newRecord = new LevelRecord(LEVEL_ID, roundsCompleted, 1);
|
||||||
|
levelRecordDao.insert(newRecord);
|
||||||
|
showNewRecordToast(roundsCompleted);
|
||||||
|
} else {
|
||||||
|
boolean isNewRecord = false;
|
||||||
|
|
||||||
|
if (roundsCompleted > existingRecord.bestScore) {
|
||||||
|
existingRecord.bestScore = roundsCompleted;
|
||||||
|
isNewRecord = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
existingRecord.attemptsCount++;
|
||||||
|
levelRecordDao.update(existingRecord);
|
||||||
|
|
||||||
|
if (isNewRecord) {
|
||||||
|
showNewRecordToast(roundsCompleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
requireActivity().runOnUiThread(() ->
|
||||||
|
Toast.makeText(requireContext(), "Ошибка сохранения: " + e.getMessage(), Toast.LENGTH_SHORT).show()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNewRecordToast(int score) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
"Новый рекорд: " + score + " раундов", Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showExitConfirmationDialog() {
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Закончить упражнение?")
|
||||||
|
.setMessage("Вы точно хотите закончить упражнение?")
|
||||||
|
.setPositiveButton("Да", (dialog, which) -> {
|
||||||
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
|
navController.popBackStack();
|
||||||
|
})
|
||||||
|
.setNegativeButton("Нет", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void navigateHome() {
|
||||||
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
|
navController.popBackStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null && previousTitle != null) {
|
||||||
|
actionBar.setTitle(previousTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (database != null) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.GridLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.OnBackPressedCallback;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class fragment_task3 extends Fragment {
|
||||||
|
|
||||||
|
private static final String ARG_PARAM1 = "param1";
|
||||||
|
private static final String ARG_PARAM2 = "param2";
|
||||||
|
private static final int LEVEL_ID = 3;
|
||||||
|
|
||||||
|
private AppDatabase database;
|
||||||
|
private LevelRecordDao levelRecordDao;
|
||||||
|
private Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
private String mParam1;
|
||||||
|
private String mParam2;
|
||||||
|
private String previousTitle;
|
||||||
|
private boolean isGameComplete = false;
|
||||||
|
|
||||||
|
private GridLayout gridLayout;
|
||||||
|
private TextView roundTextView;
|
||||||
|
private TextView livesTextView;
|
||||||
|
private List<Integer> sequence = new ArrayList<>();
|
||||||
|
private List<Integer> userSequence = new ArrayList<>();
|
||||||
|
private int currentRound = 1;
|
||||||
|
private int lives = 3;
|
||||||
|
private int rows = 3;
|
||||||
|
private int cols = 3;
|
||||||
|
private final int SHOW_TIME = 4500;
|
||||||
|
|
||||||
|
public fragment_task3() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
public static fragment_task3 newInstance(String param1, String param2) {
|
||||||
|
fragment_task3 fragment = new fragment_task3();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_PARAM1, param1);
|
||||||
|
args.putString(ARG_PARAM2, param2);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (getArguments() != null) {
|
||||||
|
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||||
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
|
}
|
||||||
|
|
||||||
|
database = AppDatabase.getDatabase(requireContext());
|
||||||
|
levelRecordDao = database.levelRecordDao();
|
||||||
|
|
||||||
|
executor.execute(() -> {
|
||||||
|
LevelRecord existingRecord = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
if (existingRecord != null) {
|
||||||
|
existingRecord.attemptsCount++;
|
||||||
|
levelRecordDao.update(existingRecord);
|
||||||
|
} else {
|
||||||
|
LevelRecord newRecord = new LevelRecord(LEVEL_ID, 0, 1);
|
||||||
|
levelRecordDao.insert(newRecord);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(true) {
|
||||||
|
@Override
|
||||||
|
public void handleOnBackPressed() {
|
||||||
|
if (!isGameComplete) {
|
||||||
|
showExitConfirmationDialog();
|
||||||
|
} else {
|
||||||
|
setEnabled(false);
|
||||||
|
navigateHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
requireActivity().getOnBackPressedDispatcher().addCallback(this, backPressedCallback);
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setTitle("Упражнение 3");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_task3, container, false);
|
||||||
|
|
||||||
|
gridLayout = view.findViewById(R.id.gridLayout);
|
||||||
|
roundTextView = view.findViewById(R.id.roundTextView);
|
||||||
|
livesTextView = view.findViewById(R.id.livesTextView);
|
||||||
|
|
||||||
|
setupGame();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupGame() {
|
||||||
|
sequence.clear();
|
||||||
|
userSequence.clear();
|
||||||
|
gridLayout.removeAllViews();
|
||||||
|
|
||||||
|
gridLayout.setRowCount(rows);
|
||||||
|
gridLayout.setColumnCount(cols);
|
||||||
|
|
||||||
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||||
|
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||||
|
int screenWidth = displayMetrics.widthPixels;
|
||||||
|
int cellSize = (int) (screenWidth * 0.8 / cols);
|
||||||
|
|
||||||
|
int totalCells = rows * cols;
|
||||||
|
for (int i = 1; i <= totalCells; i++) {
|
||||||
|
sequence.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.shuffle(sequence);
|
||||||
|
|
||||||
|
for (int i = 0; i < totalCells; i++) {
|
||||||
|
Button button = new Button(getContext());
|
||||||
|
button.setTag(sequence.get(i));
|
||||||
|
button.setText(String.valueOf(sequence.get(i)));
|
||||||
|
button.setTextSize(24);
|
||||||
|
//button.setBackgroundResource(R.drawable.cell_background);
|
||||||
|
|
||||||
|
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
|
||||||
|
params.width = cellSize;
|
||||||
|
params.height = cellSize;
|
||||||
|
params.rowSpec = GridLayout.spec(i / cols, 1f);
|
||||||
|
params.columnSpec = GridLayout.spec(i % cols, 1f);
|
||||||
|
params.setMargins(4, 4, 4, 4);
|
||||||
|
|
||||||
|
button.setLayoutParams(params);
|
||||||
|
gridLayout.addView(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUI();
|
||||||
|
|
||||||
|
new Handler().postDelayed(this::hideNumbers, SHOW_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideNumbers() {
|
||||||
|
for (int i = 0; i < gridLayout.getChildCount(); i++) {
|
||||||
|
Button button = (Button) gridLayout.getChildAt(i);
|
||||||
|
button.setText("");
|
||||||
|
button.setOnClickListener(v -> {
|
||||||
|
Button clickedButton = (Button) v;
|
||||||
|
int number = (int) clickedButton.getTag();
|
||||||
|
userSequence.add(number);
|
||||||
|
clickedButton.setText(String.valueOf(number));
|
||||||
|
|
||||||
|
if (userSequence.size() == sequence.size()) {
|
||||||
|
checkSequence();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSequence() {
|
||||||
|
boolean isCorrect = true;
|
||||||
|
for (int i = 0; i < sequence.size(); i++) {
|
||||||
|
if (!sequence.get(i).equals(userSequence.get(i))) {
|
||||||
|
isCorrect = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCorrect) {
|
||||||
|
currentRound++;
|
||||||
|
// Проверяем и обновляем рекорд сразу при увеличении раунда
|
||||||
|
checkAndUpdateRecord(currentRound);
|
||||||
|
|
||||||
|
Toast.makeText(getContext(), "Правильно! Раунд " + currentRound, Toast.LENGTH_SHORT).show();
|
||||||
|
new Handler().postDelayed(this::setupGame, 1500);
|
||||||
|
} else {
|
||||||
|
lives--;
|
||||||
|
if (lives <= 0) {
|
||||||
|
gameOver();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getContext(), "Ошибка! Осталось жизней: " + lives, Toast.LENGTH_SHORT).show();
|
||||||
|
new Handler().postDelayed(this::setupGame, 1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAndUpdateRecord(int currentRound) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
LevelRecord record = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
if (record != null && currentRound > record.bestScore) {
|
||||||
|
record.bestScore = currentRound;
|
||||||
|
levelRecordDao.update(record);
|
||||||
|
showNewRecordToast(currentRound);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNewRecordToast(int round) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
"Новый рекорд: " + round + " раундов", Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gameOver() {
|
||||||
|
isGameComplete = true;
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Игра окончена")
|
||||||
|
.setMessage("Вы прошли " + (currentRound - 1) + " раундов")
|
||||||
|
.setPositiveButton("OK", (dialog, which) -> navigateHome())
|
||||||
|
.setCancelable(false)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUI() {
|
||||||
|
roundTextView.setText("Раунд: " + currentRound);
|
||||||
|
|
||||||
|
StringBuilder hearts = new StringBuilder();
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
hearts.append(i < lives ? "❤️" : "");
|
||||||
|
}
|
||||||
|
livesTextView.setText(hearts.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showExitConfirmationDialog() {
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Закончить упражнение?")
|
||||||
|
.setMessage("Вы точно хотите закончить упражнение?")
|
||||||
|
.setPositiveButton("Да", (dialog, which) -> {
|
||||||
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
|
navController.popBackStack();
|
||||||
|
})
|
||||||
|
.setNegativeButton("Нет", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null && previousTitle != null) {
|
||||||
|
actionBar.setTitle(previousTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void navigateHome() {
|
||||||
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
|
navController.popBackStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (database != null) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,335 @@
|
|||||||
|
package com.kolobochki.memory;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.GridLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.OnBackPressedCallback;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class fragment_task4 extends Fragment {
|
||||||
|
|
||||||
|
private static final String ARG_PARAM1 = "param1";
|
||||||
|
private static final String ARG_PARAM2 = "param2";
|
||||||
|
private static final int LEVEL_ID = 4;
|
||||||
|
|
||||||
|
private AppDatabase database;
|
||||||
|
private LevelRecordDao levelRecordDao;
|
||||||
|
private Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
private String mParam1;
|
||||||
|
private String mParam2;
|
||||||
|
private String previousTitle;
|
||||||
|
private boolean isGameComplete = false;
|
||||||
|
|
||||||
|
private ImageView[][] cards = new ImageView[2][2];
|
||||||
|
private int[][] cardValues = new int[2][2];
|
||||||
|
private int changedRow = -1, changedCol = -1;
|
||||||
|
private int lives = 3;
|
||||||
|
private int round = 1;
|
||||||
|
private Handler handler = new Handler();
|
||||||
|
private Random random = new Random();
|
||||||
|
private TextView roundTextView;
|
||||||
|
private TextView livesTextView;
|
||||||
|
private GridLayout gridLayout;
|
||||||
|
|
||||||
|
public fragment_task4() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
public static fragment_task4 newInstance(String param1, String param2) {
|
||||||
|
fragment_task4 fragment = new fragment_task4();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_PARAM1, param1);
|
||||||
|
args.putString(ARG_PARAM2, param2);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (getArguments() != null) {
|
||||||
|
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||||
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
|
}
|
||||||
|
|
||||||
|
database = AppDatabase.getDatabase(requireContext());
|
||||||
|
levelRecordDao = database.levelRecordDao();
|
||||||
|
|
||||||
|
executor.execute(() -> {
|
||||||
|
LevelRecord existingRecord = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
if (existingRecord != null) {
|
||||||
|
existingRecord.attemptsCount++;
|
||||||
|
levelRecordDao.update(existingRecord);
|
||||||
|
} else {
|
||||||
|
LevelRecord newRecord = new LevelRecord(LEVEL_ID, 0, 1);
|
||||||
|
levelRecordDao.insert(newRecord);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(true) {
|
||||||
|
@Override
|
||||||
|
public void handleOnBackPressed() {
|
||||||
|
if (!isGameComplete) {
|
||||||
|
showExitConfirmationDialog();
|
||||||
|
} else {
|
||||||
|
setEnabled(false);
|
||||||
|
navigateHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
requireActivity().getOnBackPressedDispatcher().addCallback(this, backPressedCallback);
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setTitle("Упражнение 4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_task4, container, false);
|
||||||
|
|
||||||
|
gridLayout = view.findViewById(R.id.grid_layout);
|
||||||
|
cards[0][0] = view.findViewById(R.id.card00);
|
||||||
|
cards[0][1] = view.findViewById(R.id.card01);
|
||||||
|
cards[1][0] = view.findViewById(R.id.card10);
|
||||||
|
cards[1][1] = view.findViewById(R.id.card11);
|
||||||
|
|
||||||
|
roundTextView = view.findViewById(R.id.round_text);
|
||||||
|
livesTextView = view.findViewById(R.id.lives_text);
|
||||||
|
|
||||||
|
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
|
||||||
|
gridLayout.setUseDefaultMargins(true);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
final int row = i;
|
||||||
|
final int col = j;
|
||||||
|
cards[i][j].setOnClickListener(v -> onCardClicked(row, col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startNewRound();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startNewRound() {
|
||||||
|
if (!isAdded()) return;
|
||||||
|
|
||||||
|
roundTextView.setText("Раунд: " + round);
|
||||||
|
updateLivesDisplay();
|
||||||
|
|
||||||
|
List<Integer> availableImages = new ArrayList<>();
|
||||||
|
for (int i = 1; i <= 6; i++) {
|
||||||
|
availableImages.add(i);
|
||||||
|
}
|
||||||
|
Collections.shuffle(availableImages);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
int index = i * 2 + j;
|
||||||
|
if (index < availableImages.size()) {
|
||||||
|
cardValues[i][j] = availableImages.get(index);
|
||||||
|
setCardImage(i, j, "tile" + cardValues[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.postDelayed(() -> {
|
||||||
|
// Flip all cards to back
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
setCardImage(i, j, "tile_back");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.postDelayed(() -> {
|
||||||
|
changedRow = random.nextInt(2);
|
||||||
|
changedCol = random.nextInt(2);
|
||||||
|
|
||||||
|
int newImage;
|
||||||
|
List<Integer> currentImages = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
if (!currentImages.contains(cardValues[i][j])) {
|
||||||
|
currentImages.add(cardValues[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
newImage = random.nextInt(6) + 1;
|
||||||
|
} while (currentImages.contains(newImage));
|
||||||
|
|
||||||
|
cardValues[changedRow][changedCol] = newImage;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
setCardImage(i, j, "tile" + cardValues[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setCardsClickable(true);
|
||||||
|
|
||||||
|
}, 750);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void onCardClicked(int row, int col) {
|
||||||
|
if (!isAdded()) return;
|
||||||
|
|
||||||
|
setCardsClickable(false);
|
||||||
|
|
||||||
|
if (row == changedRow && col == changedCol) {
|
||||||
|
round++;
|
||||||
|
checkAndUpdateRecord(round);
|
||||||
|
|
||||||
|
handler.postDelayed(() -> {
|
||||||
|
if (isAdded()) startNewRound();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
lives--;
|
||||||
|
updateLivesDisplay();
|
||||||
|
|
||||||
|
if (lives <= 0) {
|
||||||
|
gameOver();
|
||||||
|
} else {
|
||||||
|
cards[changedRow][changedCol].setImageResource(
|
||||||
|
getResourceId("tile" + cardValues[changedRow][changedCol] + "_highlight")
|
||||||
|
);
|
||||||
|
|
||||||
|
handler.postDelayed(() -> {
|
||||||
|
if (!isAdded()) return;
|
||||||
|
setCardImage(changedRow, changedCol, "tile" + cardValues[changedRow][changedCol]);
|
||||||
|
startNewRound();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAndUpdateRecord(int currentRound) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
LevelRecord record = levelRecordDao.getRecordForLevel(LEVEL_ID);
|
||||||
|
if (record != null && currentRound > record.bestScore) {
|
||||||
|
record.bestScore = currentRound;
|
||||||
|
levelRecordDao.update(record);
|
||||||
|
showNewRecordToast(currentRound);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNewRecordToast(int round) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
"Новый рекорд: " + round + " раундов", Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
handler.removeCallbacksAndMessages(null);
|
||||||
|
if (database != null) {
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCardImage(int row, int col, String imageName) {
|
||||||
|
cards[row][col].setImageResource(getResourceId(imageName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getResourceId(String name) {
|
||||||
|
return getResources().getIdentifier(name, "drawable", requireContext().getPackageName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCardsClickable(boolean clickable) {
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
cards[i][j].setClickable(clickable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLivesDisplay() {
|
||||||
|
StringBuilder hearts = new StringBuilder();
|
||||||
|
for (int i = 0; i < lives; i++) {
|
||||||
|
hearts.append("❤️");
|
||||||
|
}
|
||||||
|
livesTextView.setText(hearts.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gameOver() {
|
||||||
|
isGameComplete = true;
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Игра окончена")
|
||||||
|
.setMessage("Вы прошли " + (round - 1) + " раундов!")
|
||||||
|
.setPositiveButton("OK", (dialog, which) -> navigateHome())
|
||||||
|
.setCancelable(false)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showExitConfirmationDialog() {
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Закончить упражнение?")
|
||||||
|
.setMessage("Вы точно хотите закончить упражнение?")
|
||||||
|
.setPositiveButton("Да", (dialog, which) -> {
|
||||||
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
|
navController.popBackStack();
|
||||||
|
})
|
||||||
|
.setNegativeButton("Нет", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (getActivity() != null && ((AppCompatActivity)getActivity()).getSupportActionBar() != null) {
|
||||||
|
((AppCompatActivity)getActivity()).getSupportActionBar().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
|
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
|
if (actionBar != null && previousTitle != null) {
|
||||||
|
actionBar.setTitle(previousTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void navigateHome() {
|
||||||
|
if (getView() == null) return;
|
||||||
|
|
||||||
|
NavController navController = Navigation.findNavController(requireView());
|
||||||
|
navController.popBackStack();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,106 @@
|
|||||||
package com.kolobochki.memory.ui.dashboard;
|
package com.kolobochki.memory.ui.dashboard;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import com.kolobochki.memory.LevelRecord;
|
||||||
|
import com.kolobochki.memory.MainActivity;
|
||||||
import com.kolobochki.memory.databinding.FragmentDashboardBinding;
|
import com.kolobochki.memory.databinding.FragmentDashboardBinding;
|
||||||
|
|
||||||
|
import com.kolobochki.memory.R;
|
||||||
|
import com.kolobochki.memory.AppDatabase;
|
||||||
|
import com.kolobochki.memory.GameRepository;
|
||||||
|
import com.kolobochki.memory.LevelRecordDao;
|
||||||
|
|
||||||
public class DashboardFragment extends Fragment {
|
public class DashboardFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentDashboardBinding binding;
|
private FragmentDashboardBinding binding;
|
||||||
|
private Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
private LevelRecordDao levelRecordDao;
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
@Override
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
DashboardViewModel dashboardViewModel =
|
super.onCreate(savedInstanceState);
|
||||||
new ViewModelProvider(this).get(DashboardViewModel.class);
|
// Инициализация базы данных
|
||||||
|
AppDatabase db = MainActivity.getDatabase();
|
||||||
|
levelRecordDao = db.levelRecordDao();
|
||||||
|
}
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
binding = FragmentDashboardBinding.inflate(inflater, container, false);
|
binding = FragmentDashboardBinding.inflate(inflater, container, false);
|
||||||
View root = binding.getRoot();
|
View root = binding.getRoot();
|
||||||
|
|
||||||
//final TextView textView = binding.textDashboard;
|
binding.chip.setOnClickListener(view -> {
|
||||||
//dashboardViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
|
try {
|
||||||
|
Navigation.findNavController(view).navigate(R.id.action_navigation_dashboard_to_navigation_info);
|
||||||
|
} catch (Exception e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.chip2.setOnClickListener(view -> {
|
||||||
|
Navigation.findNavController(view).navigate(R.id.action_navigation_dashboard_to_navigation_records);
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.chip4.setOnClickListener(view -> {
|
||||||
|
showResetConfirmationDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.chip3.setOnClickListener(view -> {
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Переход на другую платформу")
|
||||||
|
.setMessage("Скоро...")
|
||||||
|
.setPositiveButton("OK", null)
|
||||||
|
.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showResetConfirmationDialog() {
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Сброс статистики")
|
||||||
|
.setMessage("Вы уверены, что хотите сбросить все рекорды и статистику?")
|
||||||
|
.setPositiveButton("Сбросить", (dialog, which) -> resetAllStats())
|
||||||
|
.setNegativeButton("Отмена", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetAllStats() {
|
||||||
|
executor.execute(() -> {
|
||||||
|
// Удаляем все записи
|
||||||
|
levelRecordDao.deleteAllRecords();
|
||||||
|
|
||||||
|
// Создаем новые пустые записи для каждого уровня
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
LevelRecord record = new LevelRecord(i, 0, 0);
|
||||||
|
levelRecordDao.insert(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Показываем уведомление в UI потоке
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
"Все данные сброшены", Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
|||||||
@@ -31,6 +31,18 @@ public class HomeFragment extends Fragment {
|
|||||||
Navigation.findNavController(view).navigate(R.id.action_navigation_home_to_navigation_task1);
|
Navigation.findNavController(view).navigate(R.id.action_navigation_home_to_navigation_task1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
binding.button2.setOnClickListener(view-> {
|
||||||
|
Navigation.findNavController(view).navigate(R.id.action_navigation_home_to_navigation_task2);
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.button3.setOnClickListener(view -> {
|
||||||
|
Navigation.findNavController(view).navigate(R.id.action_navigation_home_to_navigation_task3);
|
||||||
|
});
|
||||||
|
|
||||||
|
binding.button4.setOnClickListener(view -> {
|
||||||
|
Navigation.findNavController(view).navigate(R.id.action_navigation_home_to_navigation_task4);
|
||||||
|
});
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 924 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 976 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 925 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 842 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 806 KiB |
@@ -79,4 +79,5 @@
|
|||||||
android:text="Сбросить мои данные"
|
android:text="Сбросить мои данные"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/imageView" />
|
app:layout_constraintTop_toBottomOf="@+id/imageView" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -20,12 +20,78 @@
|
|||||||
android:id="@+id/button"
|
android:id="@+id/button"
|
||||||
android:layout_width="321dp"
|
android:layout_width="321dp"
|
||||||
android:layout_height="63dp"
|
android:layout_height="63dp"
|
||||||
android:layout_marginStart="46dp"
|
android:layout_marginStart="48dp"
|
||||||
android:layout_marginTop="268dp"
|
android:layout_marginTop="140dp"
|
||||||
android:text="Начать упражнение"
|
android:text="Начать упражнение"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button2"
|
||||||
|
android:layout_width="321dp"
|
||||||
|
android:layout_height="63dp"
|
||||||
|
android:layout_marginStart="48dp"
|
||||||
|
android:layout_marginTop="260dp"
|
||||||
|
android:text="Начать упражнение"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button3"
|
||||||
|
android:layout_width="321dp"
|
||||||
|
android:layout_height="63dp"
|
||||||
|
android:layout_marginStart="48dp"
|
||||||
|
android:layout_marginTop="372dp"
|
||||||
|
android:text="Начать упражнение"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button4"
|
||||||
|
android:layout_width="321dp"
|
||||||
|
android:layout_height="63dp"
|
||||||
|
android:layout_marginStart="48dp"
|
||||||
|
android:layout_marginTop="496dp"
|
||||||
|
android:text="Начать упражнение"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView5"
|
||||||
|
android:layout_width="248dp"
|
||||||
|
android:layout_height="29dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="224dp"
|
||||||
|
android:text="Саймон говорит"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/imageView3"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView6"
|
||||||
|
android:layout_width="248dp"
|
||||||
|
android:layout_height="29dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginTop="344dp"
|
||||||
|
android:text="Числовая матрица"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/imageView3"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView7"
|
||||||
|
android:layout_width="248dp"
|
||||||
|
android:layout_height="29dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="464dp"
|
||||||
|
android:text="Найти лишнее"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/imageView3"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView4"
|
android:id="@+id/textView4"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -37,4 +103,17 @@
|
|||||||
android:translationY="-7dp"
|
android:translationY="-7dp"
|
||||||
app:layout_constraintStart_toEndOf="@+id/imageView3"
|
app:layout_constraintStart_toEndOf="@+id/imageView3"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView3"
|
||||||
|
android:layout_width="248dp"
|
||||||
|
android:layout_height="29dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginTop="108dp"
|
||||||
|
android:text="Найти пары"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/imageView3"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".fragment_info">
|
||||||
|
|
||||||
|
<!-- TODO: Update blank fragment layout -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/hello_blank_fragment"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView"
|
||||||
|
android:layout_width="375dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="1. Найти пары"
|
||||||
|
android:translationX="25dp"
|
||||||
|
android:translationY="35dp" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Статистика по уровням"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/stats_recycler"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="16dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout 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:background="@android:drawable/menuitem_background"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/roundText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:text="Раунд: 1"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/livesText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/roundText"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="❤️❤️❤️"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/centerImage"
|
||||||
|
android:layout_width="300dp"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/simon_off" />
|
||||||
|
|
||||||
|
<GridLayout
|
||||||
|
android:id="@+id/buttonsGrid"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:columnCount="2"
|
||||||
|
android:rowCount="2">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/redButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:layout_columnWeight="1"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:backgroundTint="@null"
|
||||||
|
android:drawableTint="@null"
|
||||||
|
android:focusable="false"
|
||||||
|
android:focusableInTouchMode="false"
|
||||||
|
android:foregroundTint="@null"
|
||||||
|
android:stateListAnimator="@null"
|
||||||
|
app:iconTint="@null"
|
||||||
|
tools:visibility="invisible"
|
||||||
|
style="@style/SimonButton"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/greenButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:layout_columnWeight="1"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:backgroundTint="@null"
|
||||||
|
android:drawableTint="@null"
|
||||||
|
android:focusable="false"
|
||||||
|
android:focusableInTouchMode="false"
|
||||||
|
android:foregroundTint="@null"
|
||||||
|
android:stateListAnimator="@null"
|
||||||
|
app:iconTint="@null"
|
||||||
|
tools:visibility="invisible"
|
||||||
|
style="@style/SimonButton"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/yellowButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:layout_columnWeight="1"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:backgroundTint="@null"
|
||||||
|
android:drawableTint="@null"
|
||||||
|
android:focusable="false"
|
||||||
|
android:focusableInTouchMode="false"
|
||||||
|
android:foregroundTint="@null"
|
||||||
|
android:stateListAnimator="@null"
|
||||||
|
app:iconTint="@null"
|
||||||
|
tools:visibility="invisible"
|
||||||
|
style="@style/SimonButton"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/blueButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_rowWeight="1"
|
||||||
|
android:layout_columnWeight="1"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:backgroundTint="@null"
|
||||||
|
android:drawableTint="@null"
|
||||||
|
android:focusable="false"
|
||||||
|
android:focusableInTouchMode="false"
|
||||||
|
android:foregroundTint="@null"
|
||||||
|
android:stateListAnimator="@null"
|
||||||
|
app:iconTint="@null"
|
||||||
|
tools:visibility="invisible"
|
||||||
|
style="@style/SimonButton"/>
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<!-- Информационная панель -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginBottom="24dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/roundTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="Раунд: 1" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/livesTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="❤️❤️❤️"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Контейнер для центрирования GridLayout -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<GridLayout
|
||||||
|
android:id="@+id/gridLayout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:rowCount="3"
|
||||||
|
android:columnCount="3"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"/>
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/round_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="Раунд: 1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/lives_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="❤️❤️❤️"
|
||||||
|
android:textAlignment="textEnd"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:translationX="235dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<GridLayout
|
||||||
|
android:id="@+id/grid_layout"
|
||||||
|
android:layout_width="395dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:alignmentMode="alignBounds"
|
||||||
|
android:columnCount="2"
|
||||||
|
android:rowCount="2"
|
||||||
|
android:useDefaultMargins="true">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/card00"
|
||||||
|
android:layout_width="183dp"
|
||||||
|
android:layout_height="196dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:scaleType="fitCenter" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/card01"
|
||||||
|
android:layout_width="183dp"
|
||||||
|
android:layout_height="196dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:scaleType="fitCenter" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/card10"
|
||||||
|
android:layout_width="183dp"
|
||||||
|
android:layout_height="196dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:scaleType="fitCenter" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/card11"
|
||||||
|
android:layout_width="183dp"
|
||||||
|
android:layout_height="196dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:scaleType="fitCenter" />
|
||||||
|
</GridLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:layout_marginBottom="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/level_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/best_score"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/attempts_count"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -16,6 +16,15 @@
|
|||||||
<action
|
<action
|
||||||
android:id="@+id/action_navigation_home_to_navigation_task1"
|
android:id="@+id/action_navigation_home_to_navigation_task1"
|
||||||
app:destination="@id/navigation_task1" />
|
app:destination="@id/navigation_task1" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_home_to_navigation_task2"
|
||||||
|
app:destination="@id/navigation_task2" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_home_to_navigation_task3"
|
||||||
|
app:destination="@id/navigation_task3" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_home_to_navigation_task4"
|
||||||
|
app:destination="@id/navigation_task4" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
@@ -26,6 +35,12 @@
|
|||||||
<action
|
<action
|
||||||
android:id="@+id/action_navigation_dashboard_to_navigation_home"
|
android:id="@+id/action_navigation_dashboard_to_navigation_home"
|
||||||
app:destination="@id/navigation_home" />
|
app:destination="@id/navigation_home" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_dashboard_to_navigation_info"
|
||||||
|
app:destination="@id/navigation_info" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_dashboard_to_navigation_records"
|
||||||
|
app:destination="@id/navigation_records" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
@@ -37,4 +52,48 @@
|
|||||||
android:id="@+id/action_navigation_notifications_to_navigation_home"
|
android:id="@+id/action_navigation_notifications_to_navigation_home"
|
||||||
app:destination="@id/navigation_home" />
|
app:destination="@id/navigation_home" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_task2"
|
||||||
|
android:name="com.kolobochki.memory.fragment_task2"
|
||||||
|
android:label="navigation_task2"
|
||||||
|
tools:layout="@layout/fragment_task2">
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_notifications_to_navigation_home"
|
||||||
|
app:destination="@id/navigation_home" />
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_task3"
|
||||||
|
android:name="com.kolobochki.memory.fragment_task3"
|
||||||
|
android:label="navigation_task3"
|
||||||
|
tools:layout="@layout/fragment_task3">
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_notifications_to_navigation_home"
|
||||||
|
app:destination="@id/navigation_home" />
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_task4"
|
||||||
|
android:name="com.kolobochki.memory.fragment_task4"
|
||||||
|
android:label="navigation_task4"
|
||||||
|
tools:layout="@layout/fragment_task4">
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_notifications_to_navigation_home"
|
||||||
|
app:destination="@id/navigation_home" />
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_info"
|
||||||
|
android:name="com.kolobochki.memory.fragment_info"
|
||||||
|
android:label="navigation_info"
|
||||||
|
tools:layout="@layout/fragment_info">
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_info_to_navigation_dashboard2"
|
||||||
|
app:destination="@id/navigation_dashboard" />
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_records"
|
||||||
|
android:name="com.kolobochki.memory.fragment_records"
|
||||||
|
android:label="navigation_records">
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_records_to_navigation_dashboard"
|
||||||
|
app:destination="@id/navigation_dashboard" />
|
||||||
|
</fragment>
|
||||||
</navigation>
|
</navigation>
|
||||||
@@ -13,4 +13,8 @@
|
|||||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
|
<style name="SimonButton" parent="Widget.AppCompat.Button.Borderless">
|
||||||
|
<item name="android:background">@drawable/simon_off</item>
|
||||||
|
<item name="android:stateListAnimator">@null</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Memory</string>
|
<string name="app_name">Memory</string>
|
||||||
<string name="title_home">Карта</string>
|
<string name="title_home">Упражнения</string>
|
||||||
<string name="title_dashboard">Профиль</string>
|
<string name="title_dashboard">Профиль</string>
|
||||||
<string name="title_notifications">Notifications</string>
|
<string name="title_notifications">Notifications</string>
|
||||||
<!-- TODO: Remove or change this placeholder text -->
|
<!-- TODO: Remove or change this placeholder text -->
|
||||||
|
|||||||
@@ -13,4 +13,8 @@
|
|||||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
|
<style name="SimonButton" parent="Widget.AppCompat.Button.Borderless">
|
||||||
|
<item name="android:background">@drawable/simon_off</item>
|
||||||
|
<item name="android:stateListAnimator">@null</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -10,6 +10,7 @@ lifecycleLivedataKtx = "2.8.7"
|
|||||||
lifecycleViewmodelKtx = "2.8.7"
|
lifecycleViewmodelKtx = "2.8.7"
|
||||||
navigationFragment = "2.8.8"
|
navigationFragment = "2.8.8"
|
||||||
navigationUi = "2.8.8"
|
navigationUi = "2.8.8"
|
||||||
|
roomCommonJvm = "2.7.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
@@ -22,6 +23,7 @@ lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-lived
|
|||||||
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
||||||
navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" }
|
navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" }
|
||||||
navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" }
|
navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" }
|
||||||
|
room-common-jvm = { group = "androidx.room", name = "room-common-jvm", version.ref = "roomCommonJvm" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
Reference in New Issue
Block a user