Test
بناء لعبة إكس-أو (Tic-Tac-Toe) احترافية في أندرويد ستوديو
أهلاً بك في هذا الدليل التعليمي الشامل حيث ستتعلم كيفية بناء لعبة إكس-أو احترافية باستخدام أندرويد ستوديو ولغة جافا. هذا المشروع مثالي للمبتدئين والمطورين المتوسطين الذين يتطلعون إلى تعزيز مهاراتهم في تطوير ألعاب أندرويد.
جدول المحتويات
مقدمة
ماذا ستتعلم: بنهاية هذا الدليل، ستكون قد أنشأت لعبة إكس-أو كاملة الوظائف مع خصم ذكاء اصطناعي ذكي. ستتعلم كيفية إعداد مشروع أندرويد، وتصميم واجهة مستخدم، وتطبيق منطق اللعبة، وتحسين تطبيقك بميزات متقدمة مثل الرسوم المتحركة والأنماط المخصصة.
المتطلبات الأساسية
- فهم أساسي للغة البرمجة جافا.
- معرفة ببيئة التطوير المتكاملة أندرويد ستوديو.
- تثبيت أندرويد ستوديو على جهازك. تحميل من هنا.
- تثبيت Java Development Kit (JDK). تحميل من هنا.
1. إعداد المشروع
1.1 إنشاء مشروع جديد
- افتح أندرويد ستوديو وانقر على “Start a new Android Studio project”.
- اختر “Empty Activity” وانقر على “Next”.
- قم بتهيئة مشروعك كما هو موضح في الصورة أدناه:
- Name: TicTacToePro
- Package name: com.example.tictactoepro
- Language: Java
- Minimum API level: API 21: Android 5.0 (Lollipop)
- انقر على “Finish” لإنشاء المشروع.
1.2 هيكل المشروع
بعد إنشاء المشروع، يجب أن يكون لديك الهيكل التالي في نافذة المشروع. انتبه إلى موقع ملفي `MainActivity.java` و `activity_main.xml`، حيث سنقوم بتعديلهما.
app/src/main/java/com/example/tictactoepro/MainActivity.javaapp/src/main/res/layout/activity_main.xmlapp/src/main/res/values/strings.xmlapp/src/main/AndroidManifest.xml
2. تصميم واجهة المستخدم
سنقوم بتصميم واجهة مستخدم نظيفة وبديهية للعبتنا. ستبدو النتيجة النهائية مثل الصورة أدناه، وتتضمن عنوانًا ولوحة نتائج وشبكة اللعب 3×3.
2.1 تعديل ملف activity_main.xml
استبدل محتوى ملف activity_main.xml بالكود التالي لإنشاء التخطيط الموضح أعلاه:
2.2 تعريف الأنماط في styles.xml
أضف الأنماط التالية إلى ملف styles.xml:
2.3 إضافة الرسوم المتحركة (Animations)
أنشئ ملفي رسوم متحركة في مجلد res/anim. للقيام بذلك، انقر بزر الماوس الأيمن على مجلد `res`، اختر `New` -> `Android Resource Directory`، واختر `anim` كنوع المورد. ثم، انقر بزر الماوس الأيمن على مجلد `anim` الجديد لإنشاء الملفات.
2.3.1 scale_up.xml
2.3.2 scale_down.xml
3. كتابة منطق اللعبة
سنقوم الآن بتطبيق منطق اللعبة في `MainActivity.java`. بهذا الكود، تصبح اللعبة قابلة للعب. يمكنك النقر على المربعات، وسيقوم الكمبيوتر بحركته، وستكتشف اللعبة حالات الفوز أو الخسارة أو التعادل.
3.1 تحديث ملف MainActivity.java
استبدل محتوى ملف MainActivity.java بالكود التالي:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button[][] buttons = new Button[3][3];
private boolean player1Turn = true;
private int roundCount;
private int player1Points;
private int player2Points;
private TextView textViewPlayer1;
private TextView textViewPlayer2;
private String name1, name2;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewPlayer1 = findViewById(R.id.text_view_p1);
textViewPlayer2 = findViewById(R.id.text_view_p2);
name1 = "أنت";
name2 = "الحاسوب";
textViewPlayer1.setText(String.format("%s: 0", name1));
textViewPlayer2.setText(String.format("%s: 0", name2));
// تهيئة الأزرار وربطها بحدث النقر
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
String buttonID = "button_" + i + j;
int resID = getResources().getIdentifier(buttonID, "id", getPackageName());
buttons[i][j] = findViewById(resID);
buttons[i][j].setOnClickListener(this);
}
}
FloatingActionButton buttonReset = findViewById(R.id.button_reset);
buttonReset.setOnClickListener(v -> resetBoard());
}
@Override
public void onClick(View v) {
if (!((Button) v).getText().toString().equals("")) {
return;
}
// تطبيق الأنيميشن عند النقر على الزر
animateButton(v);
if (player1Turn) {
((Button) v).setText("X");
((Button) v).setTextColor(getResources().getColor(R.color.yellowX)); // تعيين لون "X"
roundCount++;
if (checkForWin()) {
player1Wins();
return;
} else if (roundCount == 9) {
draw();
return;
}
player1Turn = false;
computerMove();
}
}
private void computerMove() {
handler.postDelayed(() -> {
// محاولة الفوز أولاً
if (!tryToWin("O")) {
// إذا لم يكن الفوز ممكنًا، حاول صد اللاعب
if (!tryToBlock()) {
// إذا لم يكن الصد ضروريًا، قم بحركة عشوائية
makeRandomMove();
}
}
if (checkForWin()) {
computerWins();
} else if (roundCount == 9) {
draw();
} else {
player1Turn = true;
}
}, 500); // تأخير 500 مللي ثانية لمحاكاة التفكير
}
private boolean tryMove(String playerMark, String actualMark) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (buttons[i][j].getText().toString().equals("")) {
buttons[i][j].setText(playerMark); // ضع العلامة مؤقتًا
if (checkForWin()) {
buttons[i][j].setText(actualMark); // ضع العلامة الفعلية إذا كانت حركة فائزة
if (actualMark.equals("O")) {
buttons[i][j].setTextColor(getResources().getColor(R.color.redO)); // تأكد من أن "O" باللون الأحمر
} else {
buttons[i][j].setTextColor(getResources().getColor(R.color.yellowX)); // تأكد من أن "X" باللون الأصفر
}
roundCount++;
return true;
}
buttons[i][j].setText(""); // تراجع عن الحركة إذا لم تكن ناجحة
}
}
}
return false;
}
private void makeRandomMove() {
Random random = new Random();
int row, col;
do {
row = random.nextInt(3);
col = random.nextInt(3);
} while (!buttons[row][col].getText().toString().equals(""));
buttons[row][col].setText("O");
buttons[row][col].setTextColor(getResources().getColor(R.color.redO));
roundCount++;
}
private boolean tryToWin(String mark) {
return tryMove(mark, mark);
}
private boolean tryToBlock() {
return tryMove("X", "O");
}
private boolean checkForWin() {
// التحقق من جميع حالات الفوز للصفوف والأعمدة والأقطار
for (int i = 0; i < 3; i++) {
if (checkMatch(buttons[i][0], buttons[i][1], buttons[i][2])) return true;
if (checkMatch(buttons[0][i], buttons[1][i], buttons[2][i])) return true;
}
if (checkMatch(buttons[0][0], buttons[1][1], buttons[2][2])) return true;
if (checkMatch(buttons[0][2], buttons[1][1], buttons[2][0])) return true;
return false;
}
private boolean checkMatch(Button b1, Button b2, Button b3) {
return !b1.getText().toString().equals("") && b1.getText().toString().equals(b2.getText().toString()) && b1.getText().toString().equals(b3.getText().toString());
}
private void player1Wins() {
player1Points++;
Toast.makeText(this, name1 + " فاز!", Toast.LENGTH_SHORT).show();
updatePointsText();
delayResetBoard();
}
private void computerWins() {
player2Points++;
Toast.makeText(this, "الحاسوب فاز!", Toast.LENGTH_SHORT).show();
updatePointsText();
delayResetBoard();
}
private void draw() {
Toast.makeText(this, "تعادل!", Toast.LENGTH_SHORT).show();
delayResetBoard();
}
private void updatePointsText() {
textViewPlayer1.setText(String.format("%s: %d", name1, player1Points));
textViewPlayer2.setText(String.format("%s: %d", name2, player2Points));
}
private void delayResetBoard() {
handler.postDelayed(this::resetBoard, 1500); // تأخير إعادة تعيين اللوحة لمدة 1.5 ثانية
}
private void resetBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
buttons[i][j].setText("");
}
}
roundCount = 0;
player1Turn = true;
}
private void animateButton(View view) {
Animation scaleUp = AnimationUtils.loadAnimation(this, R.anim.scale_up);
Animation scaleDown = AnimationUtils.loadAnimation(this, R.anim.scale_down);
view.startAnimation(scaleUp);
view.startAnimation(scaleDown);
}
}
4. إضافة ذكاء اصطناعي
يحاول الذكاء الاصطناعي في هذه اللعبة الفوز أولاً من خلال محاولة القيام بحركة فائزة. إذا لم يتمكن من الفوز في الخطوة التالية، فإنه يحاول منع حركة اللاعب الفائزة. إذا لم يكن أي من ذلك ممكنًا، فإنه يقوم بحركة عشوائية.
4.1 فهم منطق الذكاء الاصطناعي
"عقل" الذكاء الاصطناعي موجود في دالة computerMove(). يعطي الأولوية لحركاته بالترتيب التالي:
- الفوز: التحقق مما إذا كان بإمكانه وضع "O" في مربع للفوز باللعبة على الفور. يتم التعامل مع هذا بواسطة
tryToWin("O"). - الصد: إذا لم يتمكن من الفوز، يتحقق مما إذا كان اللاعب على وشك الفوز في دوره التالي ويقوم بصدّه عن طريق وضع "O" في ذلك المكان. يتم التعامل مع هذا بواسطة
tryToBlock(). - عشوائي: إذا لم يكن أي من الخيارين أعلاه ممكنًا، فإنه يضع "O" في أي مربع عشوائي متاح.
4.2 تعزيز الذكاء الاصطناعي
يمكنك تعزيز الذكاء الاصطناعي بشكل أكبر عن طريق تطبيق خوارزميات مثل Minimax للحصول على خصم لا يمكن هزيمته.
5. تحسينات وتخصيصات
5.1 إضافة مؤثرات صوتية
عزز تجربة المستخدم عن طريق إضافة مؤثرات صوتية لنقرات الأزرار وأحداث الفوز/التعادل.
5.2 خطوط وأيقونات مخصصة
استخدم خطوطًا مخصصة عن طريق إضافتها إلى مجلد res/font وتحديث أنماطك وفقًا لذلك.
5.3 تحسين الواجهة باستخدام Material Design
استفد من مكونات Material Design للحصول على مظهر عصري واحترافي.
خاتمة
تهانينا! لقد قمت ببناء لعبة إكس-أو احترافية مع خصم ذكاء اصطناعي ذكي، وأنماط مخصصة، ورسوم متحركة. لقد زودك هذا المشروع بمهارات قيمة في تطوير أندرويد، وتطبيق منطق الألعاب، وتصميم واجهة المستخدم وتجربة المستخدم.
لا تتردد في استكشاف المزيد من المشاريع لمواصلة تعزيز مهاراتك.