برنامه بازی مار

حدودا سال پیش همین مواقع بود که با یک تمرین جالب برنامه نویسی که توسط یکی از اساتید برای دانشجوهاش مطرح شده بود برخورد کردم. این برنامه بدون استفاده از توابع گرافیکی و تنها با دستورات ساده برنامه نویسی که از عهده همه دانشجویان تازه وارد بر میاد سعی میکنه الگوریتم یک بازی ساده مار رو پیاده سازی کنه. تصمیم گرفتم که به دوست عزیزی که برای انجام این پروژه توضیح و راهنمایی خواسته بود کمک کنم.

کدی که در این پست براتون قرار میدم کد آخریه که برای این تمرین جالب نوشتم. کد رو که مینوشتم سعی کردم توضیحاتش رو هم داخلش قرار بدم تا به دوستان تازه وارد کمک بیشتری بشه.

شرح کامل تمرین بازی مار که توسط اون استاد عزیز مطرح شده بود به این شرحه:

پروژه : بازی مار
یک جدول ۱۰ در ۱۵ در نظر بگیرید، هر یک از خانه های این جدول میتواند
۱- خالی باشد که در این صورت آن را با – نمایش می دهیم،
۲- حاوی خوراکی باشد که آن را با * نمایش می دهیم.
۳- نقطه شروع باشد که با s نمایش داده می شود. (نقطه شروع همیشه در پایین ترین سطر جدول است)
۴- نقطه پایان باشد که با e نمایش داده می شود.(نقطه پایانی هم همیشه در بالاترین سطر است.)
۵- مانع باشد که که با b نمایش داده می شود.
محل موانع و خوراکی ها به صورت تصادفی تعیین می شود. محل نقطه شروع در سطر پایین و نقطه پایان در سطر بالا هم به صورت تصادفی تعیین می شود.
قوانین بازی به این صورت است.
۱- مار یک موجود انعطاف پذیر است که طول آن ۴ است. سر مار با o و بدن او با m نشان داده می شود.
۲- طول مار در بازی ثابت می ماند.
۳- با رسیدن به خانه خوراکی مار خوراکی را می خورد و ۱۰ امتیاز می گیرد.
۴- هر ۳۰ امتیاز یک جان حساب می شود.
۵- اگر مار سعی کند وارد خانه ای بشود که مانع در آن است، یا اگر سعی کند از محیط بازی خارج شود، یکی از جان های مار از او گرفته می شود( ۳۰ امتیاز). اگر مار جان نداشته باشد، مار سوخته و بازی تمام می شود.
۶- در ابتدای بازی مار بیرون سر ما در خانه s و بقیه بدن او خارج از زمین است.
۷- مار باید با گرفتن بیشترین امتیاز خود را به خانه e برساند و از آن خارج شود.
۸- کنترل حرکت مار به دست کاربر است. در هر بار :
۱- ورودی ۱ یعنی حرکت به بالا
۲- ورود ۲ یعنی حرکت به پایین
۳- رورودی ۳ یعنی حرکت به راست
۴- ورودی ۴ یعنی حرکت به چپ
۹- پس از هر بار که کاربر یک ورودی وارد می کند( هر حرکت مار) باید وضعیت جدید و امتیاز کسب شده را به کاربر نشان بدهید.

 

تصویری از اجرای برنامه:

 

دانلود دموی برنامه بازی مار

دانلود سورس برنامه بازی مار

 

نمایش کد برنامه:

// basic snake game by MohsenRSD, Codeblog.ir
//

#include "stdafx.h"

#include<cstdlib>

#include<iostream>
using namespace std;

#include <ctime>

const unsigned int numOfRows = 15;// number of numOfRows
const unsigned int numOfColumns = 10;// number of columns
const unsigned int numOfBarriers = 6;
const unsigned int numOfFoods = 4;
const unsigned int LengthOfSnake = 4;

// نشانه های اجزا بازی
const char block = 'b';
const char food = '*';
const char empty = '-';
const char start = 'S';
const char END = 'E';
const char snakeHead = 'O';
const char snakeBody = 'M';
const char nil = ' ';

// جدول اصلی بازی
// بعلاوه دو ها برای کنترل کردن خارج شدن مار از صفحه و دسترسی صحیح به حافظه قرار داده شده اند
// بنابر این سطر و ستون اول و سطر و ستون آخر ماتریس زیر داخل بازی قرار ندارد و فقط برای کنترل
// خروج مار از صفحه در نظر گرفته شده اند
char gameTable[numOfRows + 2][numOfColumns + 2];

void play();

// ساختاری که مختصات یک نقطه از از جدول را نگهداری میکند
struct Position{

    // سربارگذاری عملگر مقایسه برای مقایسه دو موقعیت
    bool operator==(const Position& right)const
    {
        if(row == right.row && col == right.col)
            return true;
        else
            return false;
    }

    int row;
    int col;
}
foodsPos[numOfFoods], // مختصات نقاطی که در آن مختصات ها غذا درون جدول بازی قرار میگیرند
barriersPos[numOfBarriers], // مختصات نقاطی که در آن مختصات ها مانع در جدول قرار میگیرند
startPos,// مختصات نقطه شروع بازی
ENDPos,// مختصات نقطه پایان بازی
snakePos[LengthOfSnake];// مختصات اعضا بدن مار

// جهت های حرکت مار
enum MoveSide{
    UP, DOWN, LEFT, RIGHT
};

// متغیری که امتیاز را نگهداری میکند
int score = 0;

// مقدار دهی اولیه به محل اعضا بدن مار
// نقطه شروع حرکت مار نقطه شروع بازیست و تمام
// اعضا بدن مار ابتدا با این نقطه مقدار دهی میشنود
void initSnake(){

    for(int i = 0 ; i < LengthOfSnake ; i++)
    {
        snakePos[i].row = startPos.row;
        snakePos[i].col = startPos.col;
    }
    gameTable[ snakePos[0].row ][ snakePos[0].col ] = snakeHead;
}

// حرکت مار بر اساس فرمان کاربر
void move(MoveSide side)
{
    // قرار دادن مقدار خالی به جای خانه آخری که مار اشغال کرده بود
    gameTable[ snakePos[LengthOfSnake-1].row ][ snakePos[LengthOfSnake-1].col ] = empty;

    // حرکت تمام اعضا بدن مار به غیر از سر به سمت جلو
    for( int i = LengthOfSnake - 2 ; i >= 0 ; i-- )
    {
        snakePos[i+1] = snakePos[i];
    }

    // تنظیم محل جدید سر مار با توجه به ورودی کاربر
    if(side == UP){
        snakePos[0].row--;
    }
    else if(side == DOWN){
        snakePos[0].row++;
    }
    else if(side == LEFT){
        snakePos[0].col--;
    }
    else if(side == RIGHT){
        snakePos[0].col++;
    }

    // توجه
    // حرکت مار از انتها به ابتدا صورت میگیرد
    // در صورتی که حرکت از سر مار شروع میشد
    // نیاز به استفاده از یک متغیر کمکی داشتیم

}

// انتخاب خانه هایی که موانع را نگهداری میکنند
void setBarriersPositions()
{
    for( int i = 0 ; i < numOfBarriers ; i++ )
    {
        while(true)
        {
            // انتخاب سطر و ستون برای طعمه ها
            barriersPos[i].row = 1 + rand() % numOfRows;
            barriersPos[i].col = 1 + rand() % numOfColumns;

            if( gameTable [ barriersPos[i].row ]
            [ barriersPos[i].col ] != empty )
                continue;
            else
                break;
        }
        gameTable[ barriersPos[i].row ][ barriersPos[i].col ] = block;

    }
}

// انتخاب خانه هایی که درون آنها غذا است
void setFoods()
{
    for( int i = 0 ; i < numOfFoods ; i++ )
    {
        while(true)
        {
            // انتخاب سطر و ستون برای طعمه ها
            foodsPos[i].row = 1 + rand() % (numOfRows);
            foodsPos[i].col = 1 + rand() % (numOfColumns);

            if( gameTable[ foodsPos[i].row ][ foodsPos[i].col ] != empty )
                continue;
            else
                break;
        }
        gameTable[ foodsPos[i].row ][ foodsPos[i].col ] = food;

    }
}

void setWall()
{
    for( int i = 0 ; i <= numOfRows+1 ; i++ )
    {
        gameTable[i][0] = nil;
        gameTable[i][numOfColumns] = nil;
    }
    for( int i = 0 ; i <= numOfColumns+1 ; i++ )
    {
        gameTable[0][i]= nil;
        gameTable[numOfRows][i] = nil;
    }
}

// انتخاب خانه های شروع و پایان بازی
void setStartAndENDPoint()
{
    startPos.row = numOfRows;
    startPos.col = 1 + rand() % ( numOfColumns);
    gameTable[ startPos.row ][ startPos.col ] = start;

    ENDPos.row = 1;
    ENDPos.col = 1 + rand() % ( numOfColumns);
    gameTable[ ENDPos.row ][ ENDPos.col ] = END;

}

// قرار دادن تمام خانه های جدول با مقدار خالی
// به جز سطر و ستون اول و آخر که بعدا با مقدار اسپیس پر میشوند
void firstInit(){
    for( int i = 1 ; i <= numOfRows ; i++ )
    {
        for( int j = 1 ; j <= numOfColumns ; j++ )
        {
            gameTable[i][j] = empty;
        }
    }
}

void reset()
{
    firstInit();
    setFoods();
    setBarriersPositions();
    setStartAndENDPoint();
    initSnake();

}

void applyChanges()
{
    // تنظیم اولیه
    firstInit();

    // قرار دادن نقاط ابتدا و انتها در جدول
    gameTable[ startPos.row ][ startPos.col ] = start;
    gameTable[ ENDPos.row ][ ENDPos.col ] = END;

    // قرار دادن خانه هایی که در آنها غذا است درون جدول
    for( int i = 0 ; i < numOfFoods ; i++ )
        gameTable[ foodsPos[i].row ][ foodsPos[i].col ] = food;

    // اعمال موانع بر روی جدول
    for( int i = 0 ; i < numOfBarriers ; i++ )
        gameTable[ barriersPos[i].row ][ barriersPos[i].col ] = block;

    // اعمال تغییرات موقعیت بدن مار بر روی جدول بازی
    for( int i = 1 ; i < LengthOfSnake ; i++ )
    {
        gameTable[ snakePos[i].row ][ snakePos[i].col ] = snakeBody;
    }

    // قرار دادن سر مار در محل صحیح بر روی جدول بازی
    gameTable[ snakePos[0].row ][ snakePos[0].col ] = snakeHead;

}

// نمایش جدول و امتیازات
void show()
{
    cout << "\n" << "\t";
    for( int l =1 ; l <= numOfRows ; l++ )
    {
        for( int k = 1 ; k <= numOfColumns ; k++ )
            cout<<gameTable[l][k]<<" ";
        cout<<"\n" << "\t";
    }
    cout << "\n" << "Score:" << score << "\n";
}

// اگر برخوردی بین سر مار با موانع رخ داده باشد ترو و اگر
// برخوردی صورت نگرفته باشد جواب فالس بازگردانده میشود
bool collission(){

    // اگر سر مار با مانع برخورد کرد
    for( int i = 0 ; i < numOfBarriers ; i++ )
        if(snakePos[0] == barriersPos[i]){
			cout<< "\a";
            return true;
		}

    // اگر سر مار از حد مجاز خارج شده
    if(snakePos[0].row > numOfRows || snakePos[0].row < 1 || snakePos[0].col > numOfColumns ||  snakePos[0].col < 1){
		cout<< "\a";
        return true;
	}

    // اگر سر مار با خودش برخورد کرد
    for( int i = 1 ; i < LengthOfSnake ; i++ )
        if(snakePos[0] == snakePos[i]){
			cout<< "\a";
            return true;
		}

    return false;

}

void setScores(){

    if(collission())
        score -= 30;

    // اگر مار به غذا رسیده ده امتیاز اضافه کن
    for( int i = 0 ; i < numOfFoods ; i++ )
        if(snakePos[0] == foodsPos[i]){

            // غذا توسط مار خورد شد
            foodsPos[i].row = 0;
            foodsPos[i].col = 0;

            score +=10;
        }
}

bool checkENDGame(){

    // اگر سر مار به نقطه پایان رسیده پیروزی را اعلام کن
    if(snakePos[0] == ENDPos){

        cout << "\n\t" << "you win! " << "\n\n" << "reset game? (y/n)";

        // پرسیدن از کاربر برای انجام دوباره بازی
        char c;
        cin >> c;
        if(c =='y')
            play();

        return true;
    }
    else
        return false;
}

void play(){

    // بازی جدید
    reset();

    // اعمال تمام تغییرات بر روی جدول
    applyChanges();

    // نمایش جدول
    show();

    while(!checkENDGame())
    {
        int input;

        cout << "\n" << "enter side of move ( 1:Up, 2:Down, 3:Left, 4:Right ):" ;

        // تعریف آرایه ای هم اندازه با مار
        Position tempSnakePos[LengthOfSnake];

        // ذخیره مختصات مار تا اگر برخوردی صورت گرفت و مختصات مار تغییر کرد
        // مختصات مار بعد از کم شدن امتیاز به نقطه فعلی بازگردانده شود
        for(int i = 0 ; i < LengthOfSnake ; i++)
            tempSnakePos[i] = snakePos[i];

        cin >> input;
        if (input == 0)
            reset();
        else if(input == 1)
            move(UP);
        else if(input == 2)
            move(DOWN);
        else if(input == 3)
            move(LEFT);
        else if(input == 4)
            move(RIGHT);

        // تنظیم امتیازات بعد از انجام حرکت
        setScores();

        // اگر برخورد صورت گرفته باشید همه مختصات بدن و سر مار را به حالت قبل بازگردان
        if(collission())
            for(int i = 0 ; i < LengthOfSnake ; i++)
                snakePos[i] = tempSnakePos[i];

        // اعمال تمام تغییرات بر روی جدول
        applyChanges();

        // پاک کردن صفحه نمایش
        system("CLS");

        // نمایش جدول
        show();

    }
}

int main()
{
    // جلوگیری از تکرار نتایج تابع رندم با اجرای مجدد بازی
    srand(time(0));

    play();
    return 0;
}

 

برنامه‌نویس ++‏C/C‏ - برنامه‌نویس سیستم‌های گرافیکی با استفاده از کتابخانه ‏OpenGL - برنامه‌نویس #‏C و ..‏

3 thoughts on “برنامه بازی مار

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

20 − شانزده =

Back To Top