We’re trying to make a game like mahjong club but we have some problems, and we cannot figure it out how to fix it. There are major problems that we need to fix.
1-) We interact second board with double click. We should make it only 1 click.
2-) When we reach the third board we cannot play with third board. We add something to see selected tiles coordinates thus, in terminal we see only z=0 and z=1 values but we also should see z=2 coordinates.
#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define WIDTH 1366
#define HEIGHT 800
#define SQUARE_SIZE 80
#define BOARD_SIZE 6
#define LAYER 3
#define MAX_VALUE 8
// Taş yapısı
typedef struct {
int value; // Taşın değeri
bool isOpen; // Taş açık mı kapalı mı?
} Tile;
// 3 boyutlu oyun tahtası yapısı
typedef struct {
Tile tiles[BOARD_SIZE][BOARD_SIZE][LAYER]; // Taşların bulunduğu matris
} Board3D;
Board3D gameBoard; // 3 boyutlu oyun tahtası
Vector3 selectedTile1 = { -1, -1, -1 }; // Seçili taşların koordinatları
Vector3 selectedTile2 = { -1, -1, -1 };
int score = 0;
int boardX, boardY, boardWidth, boardHeight; // Tahta konum ve boyutları
// Fonksiyon prototipleri
void initializeBoard();
void drawBoard();
void selectTile(int x, int y, int z);
void checkMatch();
bool canSelectTile(int x, int y, int z);
void drawMatchesAvailable(int matchesAvailable);
void shuffleBoard();
int main(void)
{
// Pencere oluşturma
InitWindow(WIDTH, HEIGHT, "3D Tile Matching Game");
// Matrisi başlatma
initializeBoard();
// Ana döngü
while (!WindowShouldClose())
{
BeginDrawing();
// Pencereyi temizle
ClearBackground(RAYWHITE);
// Matrisi çizdir
drawBoard();
// Eşleşme kontrolü
checkMatch();
// Skoru ekrana yazdır
DrawText(TextFormat("Score: %d", score), 10, 10, 20, BLACK);
EndDrawing();
}
CloseWindow();
return 0;
}
void initializeBoard()
{
// Tahta matrisini başlatma
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
for (int k = 0; k < LAYER; k++)
{
// Taş değerlerini ve açıklık durumlarını ayarla
gameBoard.tiles[i][j][k].value = GetRandomValue(1, 8);
gameBoard.tiles[i][j][k].isOpen = false;
}
}
}
// Tahtayı karıştır
shuffleBoard();
}
void drawBoard()
{
// Tahta boyutlarını hesapla
boardWidth = BOARD_SIZE * SQUARE_SIZE * LAYER;
boardHeight = BOARD_SIZE * SQUARE_SIZE;
// Tahta konumunu hesapla
boardX = (GetScreenWidth() - boardWidth) +450;
boardY = (GetScreenHeight() - boardHeight) / 2; // 200 değeri tahtanın altındaki boşluk için
// Tahtadaki her bir kareyi ziyaret et
for (int k = LAYER - 1; k >= 0; k--) // Katmanları ters sırayla ziyaret et
{
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
// Eşleşen taşlar çizilmez
if (gameBoard.tiles[i][j][k].value != -1)
{
// Taş açıksa rengi farklı yap
Color color = gameBoard.tiles[i][j][k].isOpen ? BLUE : PURPLE;
// Kare çiz
DrawRectangle(boardX + j * SQUARE_SIZE + k * 2, boardY + i * SQUARE_SIZE + k * 2, SQUARE_SIZE, SQUARE_SIZE, color);
// Kare içine değeri yaz
DrawText(TextFormat("%d", gameBoard.tiles[i][j][k].value), boardX + j * SQUARE_SIZE + SQUARE_SIZE / 2 - 10 + k * 2, boardY + i * SQUARE_SIZE + SQUARE_SIZE / 2 - 10 + k * 2, 20, BLACK);
}
}
}
}
}
bool canSelectTile(int x, int y, int z)
{
// Geçersiz dizinler için kontrol
if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || z < 0 || z >= LAYER) {
return false;
}
// Taşın koordinatlarını kullanarak, önceki ve sonraki taşların durumunu kontrol et
bool leftEmpty = (x > 0 && gameBoard.tiles[y][x - 1][z].value != -1);
bool rightEmpty = (x < BOARD_SIZE - 1 && gameBoard.tiles[y][x + 1][z].value != -1);
bool top1Empty = (z == LAYER - 1 || (z < LAYER - 1 && gameBoard.tiles[y][x][z + 1].value == -1)); // Doğru katmanı kontrol et
bool top2Empty = (z == LAYER + 1 || (z < LAYER - 1 && gameBoard.tiles[y][x][z + 1].value == -1)); // Doğru katmanı kontrol et
// Hem sol hem de sağ doluysa veya en üstte değilse seçilemez olacak
if ((leftEmpty && rightEmpty) || top1Empty || top2Empty) { // Değişiklik burada
return false;
}
// Sadece sol veya sadece sağ boşsa seçilebilir olacak
return true;
}
void selectTile(int x, int y, int z)
{
// Eğer taş zaten açıksa, seçimi kaldır
if (gameBoard.tiles[y][x][z].isOpen)
{
gameBoard.tiles[y][x][z].isOpen = false;
// Seçilen taşın koordinatlarını güncelle
if (selectedTile1.x == x && selectedTile1.y == y && selectedTile1.z == z)
{
selectedTile1.x = -1;
selectedTile1.y = -1;
selectedTile1.z = -1;
}
else if (selectedTile2.x == x && selectedTile2.y == y && selectedTile2.z == z)
{
selectedTile2.x = -1;
selectedTile2.y = -1;
selectedTile2.z = -1;
}
return;
}
// Üst katmanın taş değeri -1 ise ve altındaki katmanda bir taş varsa, alt katmandaki taşı seç
if (z < LAYER && gameBoard.tiles[y][x][z].value == -1 && gameBoard.tiles[y][x][z - 1].value != -1) {
z++;
}
// İlk tıklamada seçim yap
if (selectedTile1.x == -1 && selectedTile1.y == -1 && selectedTile1.z == -1)
{
// Seçili taşın durumunu tersine çevir
gameBoard.tiles[y][x][z].isOpen = true;
// Seçili taşın koordinatlarını güncelle
selectedTile1.x = x;
selectedTile1.y = y;
selectedTile1.z = z;
// Seçilen taşın konumunu terminale yazdır
printf("Selected tile position: (%d, %d, %d)n", x, y, z);
}
// İkinci tıklamada seçimi kaldır veya değiştir
else if ((selectedTile1.x != x || selectedTile1.y != y || selectedTile1.z != z) &&
selectedTile2.x == -1 && selectedTile2.y == -1 && selectedTile2.z == -1)
{
// Seçili taşın durumunu tersine çevir
gameBoard.tiles[y][x][z].isOpen = true;
// Seçili taşın koordinatlarını güncelle
selectedTile2.x = x;
selectedTile2.y = y;
selectedTile2.z = z;
// Seçilen taşın konumunu terminale yazdır
printf("Selected tile position: (%d, %d, %d)n", x, y, z);
}
// İkinci tıklamada seçimi kaldır
else if (selectedTile1.x == x && selectedTile1.y == y && selectedTile1.z == z)
{
// Seçili taşın durumunu kaldır
gameBoard.tiles[y][x][z].isOpen = false;
// Seçili taşın koordinatlarını sıfırla
selectedTile1.x = -1;
selectedTile1.y = -1;
selectedTile1.z = -1;
}
// İkinci tıklamada seçimi kaldır
else if (selectedTile2.x == x && selectedTile2.y == y && selectedTile2.z == z)
{
// Seçili taşın durumunu kaldır
gameBoard.tiles[y][x][z].isOpen = false;
// Seçili taşın koordinatlarını sıfırla
selectedTile2.x = -1;
selectedTile2.y = -1;
selectedTile2.z = -1;
}
}
void drawMatchesAvailable(int matchesAvailable)
{
int frequencyTwo = 0; // Frekansı 2 olan taşların sayısını saklamak için sayaç
// Eşleşebilecek taşların üzerinde yazan sayıların frekansını kontrol et
int matchCount[BOARD_SIZE * BOARD_SIZE * LAYER] = { 0 }; // Eşleşen taşların frekansını saklamak için dizi
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
for (int k = 0; k < LAYER; k++) {
if (gameBoard.tiles[i][j][k].value != -1 && canSelectTile(j, i, k))
{
matchCount[gameBoard.tiles[i][j][k].value]++;
}
}
}
}
// Frekansı 2 olan taşların sayısını hesapla
for (int i = 1; i < BOARD_SIZE * BOARD_SIZE * LAYER; i++)
{
if (matchCount[i] == 2)
{
frequencyTwo++;
}
}
if (frequencyTwo == 0) {
printf("No matchesn");
shuffleBoard();
}
// Olası eşleşme sayısını ve frekansı 2 olan taşların sayısını sağ üst köşeye yazdır
DrawText(TextFormat("Matches Available: %d", frequencyTwo), GetScreenWidth() - 400, 10, 20, BLACK);
}
void checkMatch()
{
bool selected[BOARD_SIZE][BOARD_SIZE][LAYER] = { false };
static bool alreadyPrinted = false; // Frekansı 2 olanları sadece bir kez yazdırmak için bayrak
int matchesAvailable = 0; // Eşleşebilecek taş sayısını saklamak için sayaç
int matchValues[BOARD_SIZE * BOARD_SIZE * LAYER]; // Eşleşebilecek taşların değerlerini saklamak için dizi
int matchCount[BOARD_SIZE * BOARD_SIZE * LAYER] = { 0 }; // Eşleşen taşların frekansını saklamak için dizi
// Tahtadaki her bir kareyi ziyaret et
bool isAvailable = false;
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
for (int k = 0; k < LAYER; k++) {
if (gameBoard.tiles[i][j][k].value != -1 && canSelectTile(j, i, k))
{
isAvailable = true;
break;
}
}
if (isAvailable) break;
}
}
// Her fare tıklamasında kontrol edilecek
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
int mouseX = GetMouseX();
int mouseY = GetMouseY();
// Tahtanın içinde mi kontrol et
if (mouseX >= boardX && mouseX < boardX + boardWidth && mouseY >= boardY && mouseY < boardY + boardHeight)
{
int x = (mouseX - boardX) / SQUARE_SIZE;
int y = (mouseY - boardY) / SQUARE_SIZE;
int z = 0; // Burada z değişkenini tanımlayın, çünkü 3B matriste bir z koordinatı var.
// Seçilen taşa tıklanabilir mi kontrol et
if (canSelectTile(x, y, z))
{
// Seçili taşı güncelle
selectTile(x, y, z);
// İki taş seçildi mi kontrol et
if (selectedTile1.x != -1 && selectedTile1.y != -1 && selectedTile2.x != -1 && selectedTile2.y != -1)
{
// Eşleşmeyi kontrol et
if (gameBoard.tiles[(int)selectedTile1.y][(int)selectedTile1.x][(int)selectedTile1.z].value == gameBoard.tiles[(int)selectedTile2.y][(int)selectedTile2.x][(int)selectedTile2.z].value)
{
// Eşleşen taşları kaldır
gameBoard.tiles[(int)selectedTile1.y][(int)selectedTile1.x][(int)selectedTile1.z].value = -1;
gameBoard.tiles[(int)selectedTile2.y][(int)selectedTile2.x][(int)selectedTile2.z].value = -1;
selectedTile1.x = -1;
selectedTile1.y = -1;
selectedTile1.z = -1;
selectedTile2.x = -1;
selectedTile2.y = -1;
selectedTile2.z = -1;
score += 5;
}
else
{
// Eşleşme yoksa taşları seçilmemiş yap
gameBoard.tiles[(int)selectedTile1.y][(int)selectedTile1.x][(int)selectedTile1.z].isOpen = false;
gameBoard.tiles[(int)selectedTile2.y][(int)selectedTile2.x][(int)selectedTile2.z].isOpen = false;
selectedTile1.x = -1;
selectedTile1.y = -1;
selectedTile1.z = -1;
selectedTile2.x = -1;
selectedTile2.y = -1;
selectedTile2.z = -1;
}
}
}
}
}
// Check for matches available
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
for (int k = 0; k < LAYER; k++) {
if (gameBoard.tiles[i][j][k].value != -1 && canSelectTile(j, i, k))
{
isAvailable = true;
break;
}
}
}
if (isAvailable) break;
}
}
void shuffleBoard()
{
// Her katman için rastgele sayıları ve konumları saklamak için diziler oluştur
int nonEmptyTiles[BOARD_SIZE * BOARD_SIZE][LAYER];
Vector3 nonEmptyPositions[BOARD_SIZE * BOARD_SIZE][LAYER];
int nonEmptyCount[LAYER] = { 0 }; // Her katmandaki dolu taş sayısını saklamak için bir dizi
// Her katman için boş olmayan taşların değerlerini ve konumlarını kaydet
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
for (int k = 0; k < LAYER; k++)
{
if (gameBoard.tiles[i][j][k].value != -1)
{
nonEmptyTiles[nonEmptyCount[k]][k] = gameBoard.tiles[i][j][k].value;
nonEmptyPositions[nonEmptyCount[k]][k].x = j;
nonEmptyPositions[nonEmptyCount[k]][k].y = i;
nonEmptyPositions[nonEmptyCount[k]][k].z = k;
nonEmptyCount[k]++;
}
}
}
}
// Her katman için taşları rastgele yerleştir
for (int k = 0; k < LAYER; k++) // Her katman için
{
for (int i = 0; i < nonEmptyCount[k]; i++)
{
int randomIndex;
do
{
randomIndex = GetRandomValue(0, nonEmptyCount[k] - 1);
} while (nonEmptyTiles[randomIndex][k] == -1);
// Seçilen indeksin değerini kontrol et
if (nonEmptyTiles[randomIndex][k] != -1) {
gameBoard.tiles[(int)nonEmptyPositions[i][k].y][(int)nonEmptyPositions[i][k].x][k].value = nonEmptyTiles[randomIndex][k];
nonEmptyTiles[randomIndex][k] = -1; // Karıştırılan taşı işaretle
}
}
}
}
Emrehan Metin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.