草庐IT

Visual C++实现俄罗斯方块游戏实战二:界面设计与实现(附源码和资源 可用于大作业)

showswoller 2023-04-17 原文

需要源码和资源请点赞关注收藏后评论区留言私信~~~

我们的Visual C++工程采用MFC框架模式,下面讲解各个功能模块的界面实现

一、游戏菜单的实现

可分为如下几个步骤

1:在工程资源中添加一个菜单资源

2:给每个菜单栏添加响应函数到CTertisView类中

3:菜单响应函数应该尽量调用类中的其他功能函数,减少直接处理的过程,这样程序代码阅读起来结构简单,功能明确,菜单响应函数代码如下

// TetrisView.cpp : implementation of the CTetrisView class
//

#include "stdafx.h"
#include "Tetris.h"

#include "TetrisDoc.h"
#include "TetrisView.h"

#include "HelpDlg.h"
#include "HeroDlg.h"
#include "LevelDlg.h"
#include "Russia.h"

#include <mmsystem.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CTetrisView

IMPLEMENT_DYNCREATE(CTetrisView, CView)

BEGIN_MESSAGE_MAP(CTetrisView, CView)
	//{{AFX_MSG_MAP(CTetrisView)
	ON_COMMAND(IDR_ABOUT, OnAbout)
	ON_COMMAND(IDR_HERO_LIST, OnHeroList)
	ON_COMMAND(IDR_LEVEL_SETUP, OnLevelSetup)
	ON_COMMAND(IDR_PLAY_MUSIC, OnPlayMusic)
	ON_COMMAND(IDR_START_GAME, OnStartGame)
	ON_COMMAND(IDR_HELP, OnHelp)
	ON_WM_KEYDOWN()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/
// CTetrisView construction/destruction

CTetrisView::CTetrisView()
{
	m_bStart = FALSE;
}

CTetrisView::~CTetrisView()
{
}

BOOL CTetrisView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/
// CTetrisView drawing

void CTetrisView::OnDraw(CDC* pDC)
{
	CTetrisDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	CDC Dc;
	if(Dc.CreateCompatibleDC(pDC)==FALSE)
		AfxMessageBox("Can't create DC");
	//没有开始,显示封面
	if( m_bStart)
	{
		russia.DrawBK(pDC);
	}

}

/
// CTetrisView printing

BOOL CTetrisView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CTetrisView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CTetrisView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/
// CTetrisView diagnostics

#ifdef _DEBUG
void CTetrisView::AssertValid() const
{
	CView::AssertValid();
}

void CTetrisView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CTetrisDoc* CTetrisView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTetrisDoc)));
	return (CTetrisDoc*)m_pDocument;
}
#endif //_DEBUG

/
// CTetrisView message handlers
void CTetrisView::OnAbout() 
{
	CAboutDlg aboutDlg;		//生成关于对话框
	aboutDlg.DoModal();		//弹出关于对话框
}

void CTetrisView::OnHeroList() 
{
	CHeroDlg dlg;			//生成英雄榜对话框
	dlg.DoModal();			//弹出英雄榜对话框
}

void CTetrisView::OnLevelSetup() 
{
	CLevelDlg	dlg;	//生成等级设置对话框
	dlg.DoModal();			//弹出等级设置对话框
}

void CTetrisView::OnPlayMusic() 
{
	CWnd*   pMain   =   AfxGetMainWnd();   
	CMenu*   pMenu   =   pMain->GetMenu();
	//判断播放音乐菜单当前状态
	BOOL bCheck = (BOOL)pMenu->GetMenuState(IDR_PLAY_MUSIC, MF_CHECKED);
	
	if(m_bStart)
	{
		if(bCheck)
		{
			pMenu->CheckMenuItem(IDR_PLAY_MUSIC, MF_BYCOMMAND | MF_UNCHECKED);
		}
		else
		{
			pMenu->CheckMenuItem(IDR_PLAY_MUSIC, MF_BYCOMMAND | MF_CHECKED);
		}
		
		PlayBackMusic(!bCheck);			//调用播放背景音乐功能函数
	}

}

void CTetrisView::OnStartGame() 
{
	m_bStart = true;
	russia.GameStart();					//调用RUSSIA对象的游戏开始函数
	SetTimer(1, russia.m_Speed, NULL);
}

void CTetrisView::OnHelp() 
{
	CHelpDlg dlg;						//生成帮助对话框
	dlg.DoModal();						//弹出对话框
}

void CTetrisView::PlayBackMusic(BOOL bCheck)
{
	//指定文件并播放
	if(bCheck)
	{								//播放音乐
		sndPlaySound("music.wav",SND_ASYNC); 
	}
	else
	{								//停止播放
		sndPlaySound(NULL,SND_PURGE); 
	}

}

void CTetrisView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	//没有开始
	if(!m_bStart)
		return;
	
	switch(nChar)
	{
	case VK_LEFT:
		russia.Move(KEY_LEFT);
		break;
	case VK_RIGHT:
		russia.Move(KEY_RIGHT);
		break;		
	case VK_UP:
		russia.Move(KEY_UP);
		break;
	case VK_DOWN:
		russia.Move(KEY_DOWN);
		break;
	}
	//重画
	CDC* pDC=GetDC();
	russia.DrawBK(pDC);
	ReleaseDC(pDC);

	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CTetrisView::OnTimer(UINT nIDEvent) 
{
	//下移
	russia.Move(KEY_DOWN);
	//重画
	russia.DrawBK(GetDC());
	//关闭TIME1
	KillTimer(1);
	//调整速度
	SetTimer(1, russia.m_Speed, NULL);

	CView::OnTimer(nIDEvent);
}

二、游戏帮助对话框的实现

创建一个对话框类,通过资源中的文字说明对游戏操作方法进行描述

#if !defined(AFX_HERODLG_H__6D0A81F3_A5F6_4816_899E_ACC62CDE229A__INCLUDED_)
#define AFX_HERODLG_H__6D0A81F3_A5F6_4816_899E_ACC62CDE229A__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// HeroDlg.h : header file
//

/
// CHeroDlg dialog

// CHeroDlg dialog

class CHeroDlg : public CDialog
{
	// Construction
public:
	void SetWriteFlg(BOOL bflg);
	CHeroDlg(CWnd* pParent = NULL);   // standard constructor
	
	// Dialog Data
	//{{AFX_DATA(CHeroDlg)
	enum { IDD = IDD_HERO_LIST };
	int		m_level;
	CString	m_name;
	int		m_score;
	//}}AFX_DATA
	
	
	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CHeroDlg)
public:
	virtual int DoModal();
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL
	
	// Implementation
protected:
	
	// Generated message map functions
	//{{AFX_MSG(CHeroDlg)
	virtual void OnOK();
	afx_msg void OnBtn();
	virtual BOOL OnInitDialog();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
private:
	BOOL m_bWriteflg;
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_HERODLG_H__6D0A81F3_A5F6_4816_899E_ACC62CDE229A__INCLUDED_)

类的实现比较简单,就是一个基本对话框类的结构,只对其中的知道了按钮响应函数进行实现,用于退出当前对话框

// HelpDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Tetris.h"
#include "HelpDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CHelpDlg dialog


CHelpDlg::CHelpDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHelpDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHelpDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CHelpDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHelpDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CHelpDlg, CDialog)
	//{{AFX_MSG_MAP(CHelpDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CHelpDlg message handlers

void CHelpDlg::OnOK() 
{
	// TODO: Add extra validation here
	
	CDialog::OnOK();
}

三、游戏英雄榜对话框的实现

要创建一个对话框资源和一个setup.ini配置文件,类声明如下

#if !defined(AFX_HELPDLG_H__A6CEBADE_794E_4F8C_85FB_311FC78558A3__INCLUDED_)
#define AFX_HELPDLG_H__A6CEBADE_794E_4F8C_85FB_311FC78558A3__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// HelpDlg.h : header file
//

/
// CHelpDlg dialog

class CHelpDlg : public CDialog
{
// Construction
public:
	CHelpDlg(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{{AFX_DATA(CHelpDlg)
	enum { IDD = IDD_HELP };
		// NOTE: the ClassWizard will add data members here
	//}}AFX_DATA


// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CHelpDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:

	// Generated message map functions
	//{{AFX_MSG(CHelpDlg)
	virtual void OnOK();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_HELPDLG_H__A6CEBADE_794E_4F8C_85FB_311FC78558A3__INCLUDED_)

类的实现中通过调用系统API函数对配置文件进行读写操作,而设置读写标志接口函数是对类中的一个成员变量进行赋值操作,达到写入或者读取的区分,代码如下

// HeroDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Tetris.h"
#include "HeroDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CHeroDlg dialog


CHeroDlg::CHeroDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHeroDlg::IDD, pParent)
{
	m_bWriteflg = FALSE;
}


void CHeroDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHeroDlg)
	DDX_Text(pDX, IDC_LEVEL_EDIT, m_level);
	DDX_Text(pDX, IDC_NAME_EDIT, m_name);
	DDX_Text(pDX, IDC_SCORE_EDIT, m_score);
	DDV_MinMaxInt(pDX, m_score, 0, 10000);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CHeroDlg, CDialog)
	//{{AFX_MSG_MAP(CHeroDlg)
	ON_BN_CLICKED(IDOK_BTN, OnBtn)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CHeroDlg message handlers

void CHeroDlg::OnOK() 
{

}

void CHeroDlg::SetWriteFlg(BOOL bflg)
{
	m_bWriteflg = bflg;
}

int CHeroDlg::DoModal() 
{
	char pszTmp[128] = {0};

	//读取配置文件
	GetPrivateProfileString("HERO", "name", "0", 
		pszTmp, 127, ".\\setup.ini");
	m_name = CString(pszTmp);

	if(!m_bWriteflg)
	{
		GetPrivateProfileString("HERO", "score", "0", 
			pszTmp, 127, ".\\setup.ini");
		m_score = atoi(pszTmp);
		GetPrivateProfileString("HERO", "level", "0", 
			pszTmp, 127, ".\\setup.ini");
		m_level = atoi(pszTmp);
		
	}

	return CDialog::DoModal();
}

void CHeroDlg::OnBtn() 
{
	UpdateData(TRUE);
	if(m_bWriteflg)
	{
		CString tmp;
		tmp.Format("%d", m_score);
		WritePrivateProfileString("HERO", "name", m_name, ".\\setup.ini");
		WritePrivateProfileString("HERO", "score", tmp, ".\\setup.ini");
		tmp.Format("%d", m_level);
		WritePrivateProfileString("HERO", "level", tmp, ".\\setup.ini");
	}
	m_bWriteflg = FALSE;

	CDialog::OnOK();
}

BOOL CHeroDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	if(m_bWriteflg)
	{
		SetDlgItemText(IDOK_BTN, "记录");
	}
	
	return TRUE; 
}

四、游戏播放背景音乐的实现

播放游戏背景音乐,是通过调用Windows的API函数sndPlaySound来实现的,需要如下几个步骤

1:在工程文件中,添加winmm.lib静态库文件以及头文件

2:实现CTetrisView类中的PlayBackMusic成员函数

五、游戏等级设置对话框的实现

创建一个对话框资源,并往配置文件中添加一个小节用于记录设置游戏的等级,并且对确定按钮和取消按钮绑定响应函数,类的声明如下

#if !defined(AFX_LEVELDLG_H__E423F5C3_7698_4365_A009_4E6C7BC62189__INCLUDED_)
#define AFX_LEVELDLG_H__E423F5C3_7698_4365_A009_4E6C7BC62189__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// LevelDlg.h : header file
//

/
// CLevelDlg dialog

class CLevelDlg : public CDialog
{
// Construction
public:
	CLevelDlg(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{{AFX_DATA(CLevelDlg)
	enum { IDD = IDD_LEVEL_DLG };
	int		m_level;
	//}}AFX_DATA


// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CLevelDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:

	// Generated message map functions
	//{{AFX_MSG(CLevelDlg)
	virtual void OnOK();
	virtual void OnCancel();
	virtual BOOL OnInitDialog();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_LEVELDLG_H__E423F5C3_7698_4365_A009_4E6C7BC62189__INCLUDED_)

游戏等级设置对话框通过初始化对话框时,把配置文件中的当前等级参数读出来并显示,然后根据用户单击确定按钮进行相应的写入操作,类的实现代码如下

// LevelDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Tetris.h"
#include "LevelDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CLevelDlg dialog


CLevelDlg::CLevelDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CLevelDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CLevelDlg)
	m_level = 0;
	//}}AFX_DATA_INIT
}


void CLevelDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CLevelDlg)
	DDX_Text(pDX, IDC_LEVEL_EDIT, m_level);
	DDV_MinMaxInt(pDX, m_level, 1, 10);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CLevelDlg, CDialog)
	//{{AFX_MSG_MAP(CLevelDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CLevelDlg message handlers

void CLevelDlg::OnOK() 
{
	if(UpdateData(TRUE))
	{
		CString tmp;
		tmp.Format("%d", m_level);
		WritePrivateProfileString("SETUP", "level", tmp, ".\\setup.ini");
		CDialog::OnOK();
	}
}

void CLevelDlg::OnCancel() 
{

	CDialog::OnCancel();
}

BOOL CLevelDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	char pszTmp[128] = {0};

	GetPrivateProfileString("SETUP", "level", "0", 
		pszTmp, 127, ".\\setup.ini");
	m_level = atoi(pszTmp);

	UpdateData(FALSE);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

测试效果如下

 

 

 

创作不易 觉得有帮助请点赞关注收藏~~~

有关Visual C++实现俄罗斯方块游戏实战二:界面设计与实现(附源码和资源 可用于大作业)的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  3. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  6. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  7. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  8. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

  9. ruby - "public/protected/private"方法是如何实现的,我该如何模拟它? - 2

    在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定

  10. ruby-on-rails - self 在 Rails 模型中的值(value)是什么?为什么没有明显的实例方法可用? - 2

    我的rails3.1.6应用程序中有一个自定义访问器方法,它为一个属性分配一个值,即使该值不存在。my_attr属性是一个序列化的哈希,除非为空白,否则应与给定值合并指定了值,在这种情况下,它将当前值设置为空值。(添加了检查以确保值是它们应该的值,但为简洁起见被删除,因为它们不是我的问题的一部分。)我的setter定义为:defmy_attr=(new_val)cur_val=read_attribute(:my_attr)#storecurrentvalue#makesureweareworkingwithahash,andresetvalueifablankvalueisgiven

随机推荐