membuat game mencocokan objek dengan

27

Upload: others

Post on 10-Dec-2021

9 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Membuat Game Mencocokan Objek dengan
Page 2: Membuat Game Mencocokan Objek dengan

Membuat Game Mencocokan Objek denganC++ (Part 5)

Oleh: Sendy PK

Pada Tutorial kali  ini kita akan menambahkan lebih banyak pilihanuntuk menyesuaikan dalam game. Kita akan menambahkan kemampuanbagi pengguna untuk menyesuaikan ukuran blok dan jumlah blok di boardgame. Dalam rangka untuk mendapatkan nilai-nilai dari user kita akanmembuat dialog box untuk memint...

Pada Tutorial kali ini kita akan menambahkan lebih banyak pilihan untuk menyesuaikan dalamgame. Kita akan menambahkan kemampuan bagi pengguna untuk menyesuaikan ukuran blok danjumlah blok di board game. Dalam rangka untuk mendapatkan nilai-nilai dari user kita akanmembuat dialog box untuk meminta mereka untuk masukan.

Langkah pertama adalah untuk memperbarui game board dan dokumen kelas untuk dapatmenyesuaikan pilihan ini. Dimulai dengan game board ,kita akan membuat beberapa penyesuaianyang sangat kecil untuk file header saja. Kita sudah memiliki fungsi "getter" di kelas game boarduntuk mendapatkan nilai-nilai lebar dan tinggi dari blok dalam piksel dan jumlah baris dan kolom diboard tulis. Sekarang kita akan menambahkan fungsi "setter" untuk mengatur nilai-nilainya. Updatewilayah fungsi accessor pada game board di kelas SameGameBoard.h seperti berikut ini.

/* Accessor functions to get/set board size information */int GetWidth(void) const { return m_nWidth; }void SetWidth(int nWidth)

Page 3: Membuat Game Mencocokan Objek dengan

{ m_nWidth = (nWidth >= 3) ? nWidth : 3; }int GetHeight(void) const { return m_nHeight; }void SetHeight(int nHeight){ m_nHeight = (nHeight >= 3) ? nHeight : 3; }int GetColumns(void) const { return m_nColumns; }void SetColumns(int nColumns){ m_nColumns = (nColumns >= 5) ? nColumns : 5; }int GetRows(void) const { return m_nRows; }void SetRows(int nRows){ m_nRows = (nRows >= 5) ? nRows : 5; }

Kita telah menambahkan set function setelah get function untuk lebih mudah dibaca dan memahamikelas. Fungsi yang cukup sederhana, kita menggunakan tes sederhana pada masing-masing nilaimemastikan bahwa mereka tidak pergi di bawah nilai tertentu, tiga untuk pixel tinggi / lebar danlima untuk nilai baris / kolom. Jumlah yang lebih kecil dari ini akan mengacaukan estetika padagame board.

Berikutnya kita update dokumen dengan cara yang sama yaitu tambahkan fungsi "setter" untukmenuju fungsi"getter". Fungsi-fungsi ini ditambahkan ke SameGameDoc.h file header pada gameboard seperti berikut.

int GetWidth(void) { return m_board.GetWidth(); }void SetWidth(int nWidth) { m_board.SetWidth(nWidth); }int GetHeight(void) { return m_board.GetHeight(); }void SetHeight(int nHeight) { m_board.SetHeight(nHeight); }int GetColumns(void) { return m_board.GetColumns(); }void SetColumns(int nColumns) { m_board.SetColumns(nColumns); }int GetRows(void) { return m_board.GetRows(); }void SetRows(int nRows) { m_board.SetRows(nRows); }

Sekarang yang akan kita lakukan adalah mengubah ukuran game board, mengubah ukuran jendeladan member warna semua ini ada di event handler pada pilihan menu. Kita akan membuat dialogbaru untuk melakukannya. Membuat dialog baru dengan cara Open Resource View dibawah "View"menu "Source View" atau tombol akselerator Ctrl + Shift + E. Anda akan mengenali pandangan inidari ketika kita diedit sistem menu untuk game kita. Kali ini bukan membuka opsi Menu, buka opsiDialog. Anda akan melihat bahwa ada satu dialog sudah ada dengan ID dari IDD_ABOUTBOX. JikaAnda perhatikan di bawah menu About ada dialog yang muncul dengan informasi "About”. Dialog inisecara otomatis dihasilkan oleh MFC Application Wizard pada saat kita pertama kali set up project.Tambahkan dialog baru, cukup klik-kanan pada pilihan Dialog di Source View dan pilih "InsertDialog" dan New, sebagian besar masih kosong, dialog akan muncul dengan ID dari IDD_DIALOG1seperti gambar di bawah.

Page 4: Membuat Game Mencocokan Objek dengan

Setelah Anda klik dua kali pada pilihan IDD_DIALOG1, editor dialog akan muncul di jendela utamadalam Visual Studio, lalu akan tampil seperti gambar berikut

Kita akan menggunakan dialog ini untuk meminta pengguna untuk kedua board ukuran, baris dankolom, dan ukuran blok, lebar dan tinggi, jadi kita harus membuatnya generik. Dialog ini tidak akanberbuat banyak sampai kita menambahkan beberapa kontrol baru. Kita akan menambahkan label,mengedit kotak, dan tombol lain untuk dialog untuk membuatnya fberfungsi. Pertama kita perluuntuk membuka editor Toolbox dialog melalui menu View kemudian "Toolbox" atau Ctrl + Alt + X.Mari kita lihat pada Toolbox.

Page 5: Membuat Game Mencocokan Objek dengan

Ini adalah daftar dari Common Controls. Kita akan menggunakan "Static Text" kontrol untukmenunjukkan apa yang input pengguna yang seharusnya masukan untuk masing-masing "KontrolEdit". Kita juga akan menambahkan sebuah tombol untuk memungkinkan pengguna untukmengembalikan nilai default. Untuk menambahkan kontrol, cukup klik dan tarik kontrol yangdiinginkan dari Toolbox tepat untuk dialog dalam Dialog Editor. Mari kita mulai dengan tombol, klikdan tarik salah satu tepat di bawah Ok dan Cancel, seperti berikut.

Page 6: Membuat Game Mencocokan Objek dengan

Untuk mengubah teks pada tombol, klik pada button1 lalu pada text properti ketikkan "Default".Sekarang kita perlu beberapa "Edit Controls" tambahnya. Klik dan tarik beberapa pada dialog.Dalam rangka untuk garis mereka Anda dapat klik pada penguasa atas dan ke kiri dalam DialogEditor untuk membuat panduan yang snap ke kontrol. Saya telah menambahkan beberapa untukberbaris mengedit kontrol saya dengan tombol.

Sekarang kita tambahkan beberapa "Static Text" kontrol untuk menjelaskan kepada pengguna apayang diketik ke dalam Edit Controls. Tambahkan dua new guides yang akan melapisi teks statissampai ke tengah mengedit kontrol dan memperluas ukuran teks statis. Kontrol teks ini akanmemiliki teks mereka dimasukkan pemrograman sehingga dapat berubah tergantung pada jenis datayang kita inginkan.

Page 7: Membuat Game Mencocokan Objek dengan

Sekarang kita akan mengubah judul dialog, teks statis dan nilai-nilai dalam mengedit kontrol. Untukmelakukannya kita perlu membuat beberapa perubahan pada ID dari kontrol yang kita telahmenambahkan. Ketika mereka duduk kita tidak dapat berinteraksi dengan kontrol Teks Static;mereka membutuhkan ID baru. Tarik jendela properti dengan menekan Alt + Enter atau dari menuView-> Windows- Lain> Properties Window. Ketika Anda mengklik pada kontrol, properti untukkontrol yang akan datang. Saya sudah memilih opsi ID yang perlu diubah.

Page 8: Membuat Game Mencocokan Objek dengan

ID IDC_STATIC adalah ID disediakan yaitu untuk semua kontrol teks statis generic, kita ubahmenjadi IDC_STATIC_TEXT_1. Lalu kita ubah ID untuk semua kontrol dan dialog. Untuk melakukanhal ini, biarkan jendela properti dan klik pada kontrol yang berbeda. Hal ini akan mengisi propertiuntuk itu kontrol tertentu. Kemudian hanya mengubah ID. Kita akan membutuhkan teks statis atasmenjadi IDC_STATIC_TEXT_1 dan lainnya IDC_STATIC_TEXT_2. Kemudian mengubah namamengedit kontrol untuk IDC_EDIT_VALUE_1 untuk bagian atas kontrol edit dan IDC_EDIT_VALUE_2lainnya. Kita melakukan ini agar kita secara dinamis dapat mengubah teks tergantung pada datayang kita ingin pengguna untuk memasukkan. Tombol kita menambahkan untuk "Default" kita akanmengubah nama untuk IDC_BUTTON_DEFAULTS. Akhirnya mengubah ID dialog dari IDD_DIALOG1ke IDD_DIALOG_OPTIONS. Perubahan ini akan membantu saat membuat dialog dan menampilkankepada pengguna.

Setelah dialog diatur dalam editor dialog, kita perlu untuk menghasilkan kode untuk itu. Cukup

Page 9: Membuat Game Mencocokan Objek dengan

sederhana, klik kanan pada dialog itu sendiri, tidak ada kontrol, dan pilih "Add Class ..." kita akanmelihat MFC Class Wizard. Ini memberi kita sebuah kelas yang mewakili dialog ini yang telah kitabuat yang kita dapat gunakan dalam kode kita. Tambahkan nama kelas COptionsDialog dansemuanya akan mengisi sendirinya. Mengklik finish akan menghasilkan file OptionsDialog.h danOptionsDialog.cpp.

Sebelum kita melihat kode yang telah dibuat bagi kita mari kita membuat beberapa variabel di kelasini yang mewakili kontrol yang kita menambahkan. Kembali ke editor dialog dan klik kanan padamasing-masing kontrol, satu per satu, dan pilih "Add Variable " untuk membuka Add MemberVariabel Wizard. Ini akan menambahkan variabel ke kelas yang baru saja kita buat danmengasosiasikannya dengan kontrol yang kita benar-diklik. Saat kita pertama kali mengklik kontrolteks statis wizard akan terlihat seperti gambar di bawah ini. Isi Nama Variabel denganm_ctrlStaticText1 seperti yang saya lakukan dan klik Finish. Ini akan menambahkan semua kodeyang diperlukan untuk kelas dialog.

Page 10: Membuat Game Mencocokan Objek dengan

Kita ingin variabel kontrol dari jenis CStatic sehingga kita dapat mengubah teks dalam kontrol teksstatis setiap kali kita inginkan. Kita akan memilih pilihan yang berbeda ketika kita sampai ke editkontrol. Ulangi ini dengan kontrol teks statis kedua memberikan nama variabel m_ctrlStaticText2.

Sekarang klik kanan pada kontrol edit pertama dan pilih "Add Variable ..." Kali ini kita ingin "KontrolVariabel" tetapi variabel kontrol Nilai jadi drop-down "Kategori" dan pilih nilai. Ini akan mengubah"Variabel Type" pilihan dari jenis kontrol MFC untuk jenis nilai default menjadi CString, tapi pilih"int". Ketik nama variabel m_nValue1. Di sini kita menetapkan integer sebagai tempat penyimpananuntuk nilai di kontrol edit dan ketika pengguna mengklik Ok, nilai yang akan disimpan dalamvariabel yang telah kita buat tanpa kita menulis kode untuk melakukannya. Lihat gambar di bawahuntuk melihat apa yang kita lakukan.

Page 11: Membuat Game Mencocokan Objek dengan

Ulangi proses ini dengan kontrol edit kedua dan beri nama m_nValue2.

Sekarang kita akan menambahkan event-handler kelas untuk tombol Default. Cukup klik kanan padatombol dan pilih "Add Event Handler ..." lalu akan muncul Event Handler Wizard yang akanmemungkinkan Anda untuk membuat segala macam event untuk semua kelas Anda. Jika Andamengklik kanan pada tombol Default wizard akan default ke BN_CLICKED, yang merupakansingkatan dari tombol diklik, event untuk tombol default. Cukup klik "Add dan Edit" dan Anda akandibawa ke kode pilihan dialog di mana event handler tombol akan menunggu untuk Anda.

Page 12: Membuat Game Mencocokan Objek dengan

Terakhir yang kita akan butuhkan adalah override untuk fungsi OnInitDialog. Dari headerOptionsDialog membuka jendela properti dan pilihOverride Buttons. Lalu akan tampil daftaroverride, kita sedang mencari untuk OnInitDialog. Klik drop-down dan Add OnInitDialog. akanterlihat seperti gambar di bawah ini.

Pada poin ini akan ada banyak MFC yang dihasilkan oleh kode, pertama mari kita lihat, dantambahkan, file header OptionsDialog.h. Berikut adalah source codenya.

#pragma once

Page 13: Membuat Game Mencocokan Objek dengan

#include "afxwin.h"

// COptionsDialog dialogclass COptionsDialog : public CDialog{ DECLARE_DYNAMIC(COptionsDialog)public: // Standard Constructor COptionsDialog(bool bRowColumn, CWnd* pParent = NULL); virtual ~COptionsDialog(); // Dialog Data enum { IDD = IDD_DIALOG_OPTIONS };protected: // DDX/DDV support virtual void DoDataExchange(CDataExchange* pDX); DECLARE_MESSAGE_MAP()public: CStatic m_ctrlStaticText1; CStatic m_ctrlStaticText2; int m_nValue1; int m_nValue2; afx_msg void OnBnClickedButtonDefaults(); virtual BOOL OnInitDialog();private: /* Is this dialog for row/column (true) or width/height (false)? */ bool m_bRowColumnDialog;};

Kita tambahkan variabel lain ke dalam daftar argumen untuk konstruktor sehingga dialog dapatdibangun untuk kedua baris / kolom dan informasi lebar / tinggi. Jika kita lulus dalam "true" makadialog akan meminta pengguna untuk jumlah baris dan kolom pada game board. Jika itu adalah"false" dialog akan meminta lebar dan tinggi blok di game board. Berikut source codenya.

// OptionsDialog.cpp : implementation file#include "stdafx.h"#include "SameGame.h"#include "OptionsDialog.h"

// COptionsDialog dialogIMPLEMENT_DYNAMIC(COptionsDialog, CDialog)

COptionsDialog::COptionsDialog(bool bRowColumn, CWnd* pParent): CDialog(COptionsDialog::IDD, pParent) , m_nValue1(0) , m_nValue2(0) , m_bRowColumnDialog(bRowColumn){

Page 14: Membuat Game Mencocokan Objek dengan

}

COptionsDialog::~COptionsDialog(){}

void COptionsDialog::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_STATIC_TEXT_1, m_ctrlStaticText1); DDX_Control(pDX, IDC_STATIC_TEXT_2, m_ctrlStaticText2); DDX_Text(pDX, IDC_EDIT_VALUE_1, m_nValue1); DDX_Text(pDX, IDC_EDIT_VALUE_2, m_nValue2);}

BEGIN_MESSAGE_MAP(COptionsDialog, CDialog) ON_BN_CLICKED(IDC_BUTTON_DEFAULTS, &COptionsDialog::OnBnClickedButtonDefaults)END_MESSAGE_MAP()

// COptionsDialog message handlersvoid COptionsDialog::OnBnClickedButtonDefaults(){

// Do things differently for the different dialogs if(m_bRowColumnDialog) m_nValue1 = m_nValue2 = 15; // 15x15 board else m_nValue1 = m_nValue2 = 35; // 35x35 blocks // Have the controls updated to the new values UpdateData(false);

}

BOOL COptionsDialog::OnInitDialog(){ CDialog::OnInitDialog(); // Setup the dialog based on the dialog type

if(m_bRowColumnDialog) { // First update the title of the dialog SetWindowText(_T("Update Block Count")); // Next change the static text labels m_ctrlStaticText1.SetWindowText(_T("Rows")); m_ctrlStaticText2.SetWindowText(_T("Columns")); } else { // First update the title of the dialog SetWindowText(_T("Update Block Size"));

Page 15: Membuat Game Mencocokan Objek dengan

// Next change the static text labels m_ctrlStaticText1.SetWindowText(_T("Block Width")); m_ctrlStaticText2.SetWindowText(_T("Block Height")); }

return TRUE;}

Hal pertama yang kita lakukan adalah memperbarui konstruktor untuk mengambil nilai Booleanyang memberitahu kita apa jenis dialog yang kita buat. Perubahan berikutnya kita buat adalah untukmengatur ulang nilai-nilai ke default, untuk baris / kolom nilai-nilai yang baik 15 dan lebar / tingginilai-nilai yang baik 35. Kemudian untuk memperbarui kontrol dengan nilai-nilai baru yang kitaharus memanggil Fungsi UpdateData lewat di salah sebagai argumen. Argumennya adalah benderaBoolean yang menunjukkan arah update atau apa yang sedang diperbarui, kontrol (palsu) atauvariabel (benar). Melewati sejati akan me-reset perubahan yang baru saja Anda membuat denganpergi ke kontrol, membaca isi, dan menyimpannya ke variabel. Kita ingin memperbarui kontroldengan nilai baru dari variabel sehingga kita lulus dalam palsu.

Terakhir kita menempatkan kode ke dalam fungsi OnInitDialog. Ini adalah fungsi sebelum dialogpertama ditampilkan kepada pengguna. Di sinilah kita dapat mengatur dialog. Jadi untuk dialogbaris / kolom kita menetapkan judul dialog untuk "Update Blok Hitung" dengan fungsiSetWindowText dan _T () makro yang kita bicarakan dalam artikel kedua. Kemudian kitamemperbarui teks dalam kontrol teks statis dengan menggunakan fungsi dengan nama yang samadalam objek kontrol. Kita menetapkan mereka untuk "Rows" dan "Kolom". Jika itu adalah dialoglebar / tinggi kita mengubah judul dan label untuk mencerminkan hal itu. Itu adalah semua yangperlu dilakukan dalam dialog, semuanya harus berfungsi dengan baik sekarang.

Langkah terakhir kita adalah untuk mengatur beberapa event dalam tampilan untuk dua pilihanmenu yang kita bekerja dengan. Kita melakukan hal ini melalui jendela Properties dari file headeruntuk tampilan (SameGameView.h). Klik pada tombol acara, salah satu yang terlihat seperti petir,memperluas pilihan ID_SETUP_BLOCKCOUNT dan menambahkan event handler COMMAND.Lakukan ini dengan pilihan ID_SETUP_BLOCKSIZE juga.

Kita tidak perlu membuat perubahan ke tampilan ini file header selain perubahan yangmenambahkan dua penangan lakukan secara otomatis. Berikut adalah satu-satunya perubahan yangdibuat secara otomatis.

afx_msg void OnSetupBlockcount();afx_msg void OnSetupBlocksize();

Perubahan terjadi pada iplementasi atau source file dari view pada SameGameView.cpp. Untukmenggunakan opsi dialog yang baru saja kita buat kita harus menyertakan file header di file sumbertampilan ini. Berikut adalah source codenya.

#include "stdafx.h"#include "SameGame.h"

Page 16: Membuat Game Mencocokan Objek dengan

#include "SameGameDoc.h"#include "SameGameView.h"#include "OptionsDialog.h"

#ifdef _DEBUG#define new DEBUG_NEW#endif

Selanjutnya kita akan mengisi dua event handler yang baru saja kita menambahkan. Kedua fungsi inipada dasarnya sama kecuali di lima lokasi seperti source code yang kita lihat di bawah.

void CSameGameView::OnSetupBlockcount(){ // First get a pointer to the document CSameGameDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(!pDoc) return; // Create the options dialog COptionsDialog dlg(true, this); // Set the row and column values dlg.m_nValue1 = pDoc->GetRows(); dlg.m_nValue2 = pDoc->GetColumns(); // Display the dialog if(dlg.DoModal() == IDOK) { // First delete the board pDoc->DeleteBoard(); // Get the user selected values pDoc->SetRows(dlg.m_nValue1); pDoc->SetColumns(dlg.m_nValue2); // Update the board pDoc->SetupBoard(); // Resize the view ResizeWindow(); }}

void CSameGameView::OnSetupBlocksize(){ // First get a pointer to the document CSameGameDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(!pDoc) return; // Create the options dialog COptionsDialog dlg(false, this); // Set the width and height values

Page 17: Membuat Game Mencocokan Objek dengan

dlg.m_nValue1 = pDoc->GetWidth(); dlg.m_nValue2 = pDoc->GetHeight(); // Display the dialog if(dlg.DoModal() == IDOK) { // First delete the board pDoc->DeleteBoard(); // Get the user selected values pDoc->SetWidth(dlg.m_nValue1); pDoc->SetHeight(dlg.m_nValue2); // Update the board pDoc->SetupBoard(); // Resize the view ResizeWindow(); }}

Sama seperti setiap event handler lain yang sudah kita buat, pertama kita mendapatkan pointer kedokumen. Kemudian kita buat dialog dengan instantiating sebuah instance dari kelas itu. Berikutadalah perbedaan pertama antara dua fungsi. Dalam fungsi pertama, OnSetupBlockcount, kita lulusdalam nilai sebenarnya, dan dalam fungsi kedua, kita lulus dalam palsu. Dua baris berikutnya diaturinteger publik menghargai m_nValue1 dan m_nValue2 menjadi baris dan kolom untuk fungsipertama dan lebar dan tinggi untuk yang kedua. Dengan menetapkan nilai-nilai ini sebelummemanggil DoModal pada dialog kita memastikan bahwa nilai-nilai mulai di mengedit kontrol yangsesuai mereka. Baris berikutnya adalah di mana kita benar-benar pop-up dan menampilkan dialogdengan fungsi DoModal. Hal ini menunjukkan dialog dan tidak kembali kontrol untuk aplikasisampai pengguna mengklik Ok, Batal atau tombol X untuk menutup. Kemudian fungsimengembalikan nilai didasarkan pada bagaimana pengguna menutup dialog. Berikut kita uji untukOk jadi kita membandingkan nilai kembali terhadap IDOK. Jika pengguna mengklik Ok maka kitaterus melakukan perubahan. Jika tidak kita mengabaikan segala sesuatu yang terjadi danmelanjutkan.

Jika pengguna mengklik Ok pertama-tama kita harus menghapus board game tua dan membebaskanmemori. Setelah selesai kita bisa menggunakan kita "setter" fungsi pada dokumen untuk menyimpannilai-nilai bahwa pengguna yang dipilih. Ini adalah set terakhir dari perbedaan; kita menggunakansetter yang berbeda tergantung pada fungsi karena kita bekerja sama dengan nilai yang berbeda dimasing-masing fungsi. Setelah mereka ditetapkan dalam dokumen dan board game kita perlumembuat sebuah board game baru dengan memanggil SetupBoard. Ini akan membuat board gamebaru dengan opsi yang dipilih baru. Akhirnya kita mengubah ukuran jendela untuk mencocokkannomor baru baris / kolom atau ukuran blok baru. Game Anda sekarang harus dapat terlihat sepertiini.

Page 18: Membuat Game Mencocokan Objek dengan

Game kita hampir selesai. Pada tutorial ini kita menciptakan sebuah opsi dialog baru untuk dapatmeminta pengguna untuk informasi ukuran. Kita kemudian diperbarui board game yang sesuai.Pilihan ini memungkinkan pengguna untuk memiliki banyak pengalaman yang berbeda. Apa tingkatdapat Anda benar-benar jelas pada dengan board game lima baris dengan lima kolom? Ada banyakkombinasi dari pilihan yang dapat mengubah kesulitan game dan membuat Anda mengubah strategiAnda. Itulah yang membuat game menyenangkan, mulai dapat memutar ulang dengan pilihan yangberbeda dengan cara yang berbeda.

Kita hampir selesai dengan Game kita ini. Kita telah membahas beberapa topik mulai daripemrograman event driven pemrograman GDIgraphics. Banyak topik yang kita bahas melampauikesenjangan antara pemrograman game dan aplikasi pemrograman pada umumnya. Membangunaplikasi MFC adalah salah satu topik tersebut, tidak banyak game yang ditulis dalam MFC. Topiktutorial akhir ini adalah kita akan membahas bagaimana membuat sebuah undo / redo stack untukgame kita. Undo / redo merupakan fitur penting untuk sebagian besar aplikasi.

Undo / Redo Stack

Kita menyebutnya fitur ini "undo / redo stack" karena tipe data abstrak (ADT) stack. Stack adalahkoleksi objek-objek yang mirip dengan stack piring di dapur Anda, satu-satunya cara Anda bisamendapatkan pelat bawah adalah untuk pertama bergerak yang atas. Untuk menambahkan piringAnda hanya menempatkan mereka di atas stack. Dengan kata lain itu sejenis "Last In First Out"(LIFO) Ini adalah cara yang berguna untuk menyimpan bergerak terakhir Anda. Ketika Andabergerak dalam game keadaan sebelumnya diletakkan di atas stack undo sehingga dapat

Page 19: Membuat Game Mencocokan Objek dengan

dikembalikan dalam urutan terbalik bahwa itu dibuat. Cara kita akan melakukan ini adalah untukmenyimpan salinan lama objek board game di undo stack sebelum kita menghapuspotongan-potongan dari yang baru. Ketika kita membatalkan bergerak, board saat dimasukkan keredo stack dan board atas dari undo stack sekarang dewan saat ini. Operasi redo adalah justrusebaliknya, menempatkan board saat di undo stack dan mengambil board atas off dari redo stackdan membuat board saat.

Kita perlu untuk membuat beberapa perubahan untuk game board kita untuk membuatnya . Kitaperlu membuat copy constructor untuk melakukan deep copy. Cukup tambahkan fungsi prototipecopy constructor tepat antara konstruktor default dan destructor di SameGameBoard.h.

/* Default Constructor */CSameGameBoard(void);/* Copy Constructor */CSameGameBoard(const CSameGameBoard& board);/* Destructor */~CSameGameBoard(void);

Kita menggunakan deep copy constructor karena kita memiliki pointer ke beberapa memori yangdialokasikan secara dinamis. Ini berarti kita tidak bisa hanya menyalin pointer tetapi dinamismengalokasikan lebih banyak memori dan kemudian menyalin isi ke dalam ruang memori. Kitatambahkan deep copy constructor source file pada game board (SameGameBoard.cpp) denganmenambahkan fungsi implementasi.

#pragma once

#include "SameGameBoard.h"#include <stack>

class CSameGameDoc : public CDocument{protected: // create from serialization only CSameGameDoc(); virtual ~CSameGameDoc(); DECLARE_DYNCREATE(CSameGameDoc)

// Operationspublic: /* Functions for accessing the game board */ COLORREF GetBoardSpace(int row, int col) { return m_board->GetBoardSpace(row, col); } void SetupBoard(void) { m_board->SetupBoard(); } int GetWidth(void) { return m_board->GetWidth(); } void SetWidth(int nWidth) { m_board->SetWidth(nWidth); } int GetHeight(void) { return m_board->GetHeight(); } void SetHeight(int nHeight) { m_board->SetHeight(nHeight); } int GetColumns(void) { return m_board->GetColumns(); } void SetColumns(int nColumns) { m_board->SetColumns(nColumns); }

Page 20: Membuat Game Mencocokan Objek dengan

int GetRows(void) { return m_board->GetRows(); } void SetRows(int nRows) { m_board->SetRows(nRows); } void DeleteBoard(void) { m_board->DeleteBoard(); } bool IsGameOver() { return m_board->IsGameOver(); } /* Notice we removed the implementation of this function */ int DeleteBlocks(int row, int col); int GetRemainingCount() { return m_board->GetRemainingCount(); } int GetNumColors() { return m_board->GetNumColors(); } void SetNumColors(int nColors); /* Undo/redo functions */ void UndoLast(); bool CanUndo(); void RedoLast(); bool CanRedo(); // Overridespublic: virtual BOOL OnNewDocument();

protected: /* Functions to clear undo/redo stacks */ void ClearUndo(); void ClearRedo(); /* Instance of the game board--notice that we made it a pointer */ CSameGameBoard* m_board; /* Undo stack */ std::stack<CSameGameBoard*> m_undo; /* Redo stack */ std::stack<CSameGameBoard*> m_redo;

// Generated message map functionsprotected: DECLARE_MESSAGE_MAP()};

Pertama-tama kita perlu menyertakan stack header sehingga kita dapat menggunakan stack class.Karena kita akan mengubah variabel m_board ke pointer kita harus mengubah dari menggunakandot operator untuk panah atau penunjuk operator melalui setiap fungsi dalam dokumen. Berikutnyapada daftar perubahan adalah kenyataan bahwa kita bergerak pelaksanaan fungsi DeleteBlocks kesource file. Fungsi ini telah menjadi lebih terlibat dari sekedar satu baris sehingga kita akanmemindahkannya.

Kemudian kita tambahkan enam fungsi baru, empat adalah public function dan dua protectedfunction. Fungsi umum dibagi menjadi dua kelompok, satu set, UndoLast function dan RedoLast,benar-benar melakukan undo dan redo, sedangkan set kedua, CanUndo dan CanRedo, untuk tessederhana kita akan gunakan untuk mengaktifkan dan menonaktifkan pilihan menu ketika merekatidak tersedia. Protected function yang fungsi pembantu sederhana untuk membersihkan dandeallocate memori terkait dari kedua stack. Akhirnya kita menambahkan dua deklarasi stack undo /

Page 21: Membuat Game Mencocokan Objek dengan

redo.

Dengan perubahan pointer ke board game, ada beberapa hal yang perlu ditambahkan ke fungsi yangada sebelum kita menambahkan fungsi baru. Berikut ini adalah source code untuk dokumen baru diSameGameDoc.cpp

#include "stdafx.h"#include "SameGame.h"

#include "SameGameDoc.h"

#ifdef _DEBUG#define new DEBUG_NEW#endif

// CSameGameDocIMPLEMENT_DYNCREATE(CSameGameDoc, CDocument)BEGIN_MESSAGE_MAP(CSameGameDoc, CDocument)END_MESSAGE_MAP()

// CSameGameDoc construction/destructionCSameGameDoc::CSameGameDoc(){

// There should always be a game board m_board = new CSameGameBoard();

}

CSameGameDoc::~CSameGameDoc(){

// Delete the current game board delete m_board; // Delete everything from the undo stack ClearUndo(); // Delete everything from the redo stack ClearRedo();

}

BOOL CSameGameDoc::OnNewDocument(){ if (!CDocument::OnNewDocument()) return FALSE;

// Set (or reset) the game board m_board->SetupBoard(); // Clear the undo/redo stacks ClearUndo(); ClearRedo();

Page 22: Membuat Game Mencocokan Objek dengan

return TRUE;}

void CSameGameDoc::SetNumColors(int nColors){ // Set the number of colors first m_board->SetNumColors(nColors); // Then reset the game board m_board->SetupBoard();}

int CSameGameDoc::DeleteBlocks(int row, int col){ // Save the current board in the undo stack m_undo.push(new CSameGameBoard(*m_board)); // Empty out the redo stack ClearRedo(); // Then delete the blocks int blocks = m_board->DeleteBlocks(row, col); // Clear the undo stack at the end of a game if(m_board->IsGameOver()) ClearUndo(); // Return the number of blocks return blocks;}

void CSameGameDoc::UndoLast(){ // First make sure that there is a move to undo if(m_undo.empty()) return; // Take the current board and put it on the redo m_redo.push(m_board); // Take the top undo and make it the current m_board = m_undo.top(); m_undo.pop();}

bool CSameGameDoc::CanUndo(){ // Can undo if the undo stack isn't empty return !m_undo.empty();}

void CSameGameDoc::RedoLast(){ // First make sure that there is a move to redo if(m_redo.empty()) return; // Take the current board and put it on the undo

Page 23: Membuat Game Mencocokan Objek dengan

m_undo.push(m_board); // Take the top redo and make it the current m_board = m_redo.top(); m_redo.pop();}

bool CSameGameDoc::CanRedo(){ // Can redo if the redo stack isn't empty return !m_redo.empty();}

void CSameGameDoc::ClearUndo(){ // Delete everything from the undo stack while(!m_undo.empty()) { delete m_undo.top(); m_undo.pop(); }}

void CSameGameDoc::ClearRedo(){ // Delete everything from the redo stack while(!m_redo.empty()) { delete m_redo.top(); m_redo.pop(); }}

Pertama-tama kita perlu menyertakan stack kepala sehingga kita dapat menggunakan kelas stack.Karena kita akan mengubah variabel m_board ke pointer kita harus mengubah dari menggunakandot operator untuk panah atau penunjuk operator melalui setiap fungsi dalam dokumen. Berikutnyapada daftar perubahan adalah kenyataan bahwa kita bergerak pelaksanaan fungsi DeleteBlocks kefile sumber. Fungsi ini telah menjadi lebih terlibat dari sekedar satu baris sehingga kita akanmemindahkannya.

Kita kemudian menambahkan enam fungsi baru, empat adalah fungsi umum dan dua dilindungi.Fungsi umum dibagi menjadi dua kelompok, satu set fungsi, UndoLast dan RedoLast, benar-benarmelakukan undo dan redo, sedangkan set kedua, CanUndo dan CanRedo, tes sederhana kita akangunakan untuk mengaktifkan dan menonaktifkan pilihan menu ketika mereka tidak tersedia. Fungsilindung yang fungsi pembantu sederhana untuk membersihkan dan deallocate memori terkait darikedua stack. Akhirnya kita menambahkan dua deklarasi stack undo / redo.

Dengan perubahan pointer ke board game, ada beberapa hal yang perlu ditambahkan ke fungsi yangada sebelum kita menambahkan fungsi baru. Berikut ini adalah source code untuk dokumen baru diSameGameDoc.cpp

Page 24: Membuat Game Mencocokan Objek dengan

/* Functions for undo/redo */afx_msg void OnEditUndo();afx_msg void OnEditRedo();/* Functions to update the undo/redo menu options */afx_msg void OnUpdateEditUndo(CCmdUI *pCmdUI);afx_msg void OnUpdateEditRedo(CCmdUI *pCmdUI);

Sekarang mari kita lihat source file. Pada message map anda akan menemukan empat baris baruyang mengatur event, associating event, ID dan fungsi. Sekali lagi kita melihat ini sebelumnya.

ON_COMMAND(ID_EDIT_UNDO, &CSameGameView::OnEditUndo)ON_COMMAND(ID_EDIT_REDO, &CSameGameView::OnEditRedo)ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, &CSameGameView::OnUpdateEditUndo)ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, &CSameGameView::OnUpdateEditRedo)

Implementasi dari dua event ON_COMMAND cukup sederhana dan mengikuti pola yang telah kitalihat sebelumnya, mendapatkan pointer ke dokumen, memanggil fungsi pada dokumen dan akhirnyamenyebabkan view untuk redraw. Lakukan ini untuk kedua undo dan redo.

void CSameGameView::OnEditUndo(){ // First get a pointer to the document CSameGameDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(!pDoc) return; // Call undo on the document pDoc->UndoLast(); // Force the view to redraw Invalidate(); UpdateWindow();}

void CSameGameView::OnEditRedo(){ // First get a pointer to the document CSameGameDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(!pDoc) return; // Call redo on the document pDoc->RedoLast(); // Force the view to redraw Invalidate(); UpdateWindow();

Page 25: Membuat Game Mencocokan Objek dengan

}

Event handler untuk event ON_UPDATE_COMMAND_UI, pertama mendapatkan pointer ke dokumenuntuk akses ke game board.

void CSameGameView::OnUpdateEditUndo(CCmdUI *pCmdUI){ // First get a pointer to the document CSameGameDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(!pDoc) return; // Enable option if it is available pCmdUI->Enable(pDoc->CanUndo());}

void CSameGameView::OnUpdateEditRedo(CCmdUI *pCmdUI){ // First get a pointer to the document CSameGameDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(!pDoc) return; // Enable option if it is available pCmdUI->Enable(pDoc->CanRedo());}

Sekarang stack undo / redo sekarang sudah berfungsi. Periksalah pada pilihan menu undo, sekarangsudah dapat diaktifkan. Klik dan kita akan melihat original game board game. Periksa pilihan menuredo dan akan diaktifkan sekarang. Klik itu dan Anda akan kembali ke tempat sebelum undo.Berikuttampilan game yang dapat kita lihat sekarang.

Page 26: Membuat Game Mencocokan Objek dengan

Coba tekan Ctrl + Z setelah kita buat beberapa pergerakan objek dan kita akan melihat undo yangbekerja dengan keyboard. Sekarang coba tekan Ctrl + Y untuk redo. Apa itu bekerja? Tidak? Nahkita bisa memperbaikinya. Ingat bahwa pada pilihan menu untuk redo kita menunjukkan kepadapengguna bahwa Ctrl + Y akan mengirim ON_COMMAND untuk ID_EDIT_REDO. Itulah yangdisebut akselerator.

Page 27: Membuat Game Mencocokan Objek dengan

Untuk mengakses akselerator, buka Resource View dari menu View (di bawah Other Windows) atautekan accelerator dengan tekan Ctrl + Shift + E pada Visual Studio. Kemudian buka opsiAccelerator bawah SameGame.rc dan klik dua kali pada IDR_MAINFRAME untuk membukaAccelerator Editor. Pada gambar di bawah ini kita telah menambahkan akselerator untuk perintahredo.

Untuk menambahkannya, klik pada baris kosong pada akselerator terakhir, lalu di kolom ID; ini akantampil menu drop-down yang memungkinkan untuk memilih ID_EDIT_REDO, ID dari pilihan menuuntuk perintah redo; memberikan kunci Y dan modifikator Ctrl (Ctrl + Y). Sekarang kita kompilegame dan menjalankannya. Seperti yang kita telah menambahkan kombinasi keystroke yangsekarang mengirimkan ON_COMMAND untuk ID_EDIT_REDO.

Sekarang kita sudah selesai membuat game, Let’s Play and Let’s Have Fun Together :D

Tentang Penulis

Sendy PKSaya adalah Programmer yang memiliki impian untuk menguasai duniakunjungi situs pribadi saya di www.spk.my.id