Win32 游戏开发:TicTacToe(井字游戏) 上篇

1) 简单介绍"井字游戏"(TicTacToe)

是一种在3x3格子上进行的连珠游戏,和五子棋比较类似,由于棋盘一般不画边框,格线排成井字故得名。(摘抄自百度百科)

(还记得以前经常跟同桌一起在本子上玩这个呢,哈哈哈~~~(/捂脸))

2) 游戏规则

由分别代表OX的两个游戏者轮流在格子里留下标记(一般来说先手者为X)。由最先在任意一条直线上成功连接三个标记的一方获胜。(摘抄自百度百科)

3) 界面的设计

① 为什么不是先写代码?

代码固然重要,但也需要先清楚我们需要如何去做,才能更好更快地去完成任务哦~

② 井字游戏界面

井字游戏的界面很简单,所以简单草图画一下,如下:

棋盘:

"井字游戏"UI

玩家1标记:

玩家1标记图片

玩家2标记:

玩家2标记图片

PS:以上图片在游戏中不使用哦~,仅为表示大致形状

4) 游戏流程

简单做了一个流程图,如下:(工具:Microsoft Word)

井字游戏_流程图

5) 井字游戏中的游戏对象

① 什么是游戏对象?

简单来说就是在游戏中的对象,举个例子:棋盘、玩家的标记、······

② 列举井字游戏中的游戏对象

1. 棋盘

2. 玩家的标记

6) 开始正式工作啦(写代码)

① 经过上面的前期工作,我们应该更清楚我们要做什么了

1. 首先是一个基础的Win32的框架(不懂可以看下我的这篇文章)

2. 定义一个game(游戏)类进行管理游戏对象

3. 定义游戏对象类,board(棋盘)类、prece(棋子)类

4. 出于需要博主还会定义一个util(常用工具)类

不就是码代码嘛,(#^.^#)

② 码代码

1.Win32框架(...)

2.定义一个game(游戏)类

class Game
{
public:
	void Init(HWND);                // 游戏初始化
	void Render(HDC);               // 绘制游戏对象
	void DrawGameOver(HDC);         // 绘制游戏结束
	void DrawBackground(HDC);       // 绘制游戏背景
	void CheckGameOver();           // 检测是否游戏结束
	void MouseDown(int, int);       // 鼠标点击消息

private:
	Board m_board;                  // 游戏棋盘
	bool m_bIsGameOver;             // 是否结束游戏
	GameOverType m_over_type;       // 游戏结局类型
	HWND m_hWnd;                    // 窗口句柄
};

3.定义游戏对象

① board(棋盘)类

class Board
{
public:
	~Board();                       // 析构函数

public:
	void Init(HWND);                // 初始化
	void Render(HDC);               // 绘制棋盘
	void DrawBoard(HDC);            // 绘制棋盘
	void MouseDown(int, int);       // 鼠标点击消息

public:
	Prece** GetPreces() { return m_ppPreces; }    // 获取棋盘上的所有棋子

private:
	RECT m_rect;                    // 棋盘矩形
	ClickPlayer m_cur_click;        // 当前玩家
	Prece** m_ppPreces;             // 棋盘上的所有棋子
};

② prece(棋子)类

class Prece
{
public:
	Prece(int, int, int, int, int);     // 构造函数

public:
	void Render(HDC);                   // 绘制棋子
	void DrawGraphics(HDC);             // 绘制棋子点击后的图形,比如玩家1的是"×",玩家2的是"○"
	void DrawPlayer1Graphics(HDC);      // 绘制玩家1点击图形
	void DrawPlayer2Graphics(HDC);      // 绘制玩家2点击图形
	bool CheckClick(int, int);          // 当鼠标点击时候,判断鼠标是否点击到棋子
	void Click(ClickPlayer);            // 棋子被点击

public:
	bool IsClick() { return m_bIsClick; };                      // 棋子是否被点击
	ClickPlayer GetClickPlayer() { return m_click_player; }     // 获取点击该棋子的玩家
	int GetIndex() { return m_index; }                          // 获取棋子的下标

private:
	int m_index;                        // 格子的下标
	int m_x;                            // 棋子横坐标
	int m_y;                            // 棋子纵坐标
	int m_w;                            // 棋子的宽度
	int m_h;                            // 棋子的高度
	bool m_bIsClick;                    // 棋子是否被点击
	ClickPlayer m_click_player;         // 点击棋子的玩家
};

4. 博主定义的util(常用工具)类

class Util
{
public:
	static void DrawLine(HDC, int[4]);                          // 绘制一条直线
	static void CreateDoubleBuffer(HWND, HDC &, HBITMAP &);     // 创建双缓冲(兼容DC和兼容位图)
	static void CreateLogFont(HFONT &, int);                    // 创建逻辑字体
		
};

③ 代码解释

先贴上main.cpp中的代码


//++++++++++++++++++++++++++++++++++
// 宏定义
//----------------------------------
#define UNICODE              // 使用UNICODE编码,如果在编译器设置了使用UNICODE字符集此处可免
#define _UNICODE             // 使用UNICODE编码,如果在编译器设置了使用UNICODE字符集此处可免

//++++++++++++++++++++++++++++++++++
// 头文件
//----------------------------------
#include <windows.h>                                    // Win32程序最重要的头文件
#include <tchar.h>                                      // 兼容字符集头文件

#include "game.h"                                       // 游戏头文件
#include "util.h"                                       // 常用工具头文件

//++++++++++++++++++++++++++++++++++
// 全局变量
//----------------------------------
WCHAR g_lpszClassName[] = _T("TicTacToe");              // 窗口类的名称
WCHAR g_lpszWindowName[] = _T("TicTacToe");             // 窗口的名称,(也就是窗口的标题)
Game g_game;                                            // 游戏对象
HDC g_mdc;                                              // 兼容DC
HBITMAP g_bitmap;                                       // 兼容位图

//++++++++++++++++++++++++++++++++++
// 函数声明
//----------------------------------
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // 窗口消息处理过程
VOID TicTacToe_Init(HWND);                              // 井字游戏初始化
VOID TicTacToe_Render(HWND);                            // 井字游戏绘制
VOID TicTacToe_MouseDown(int, int);                     // 井字游戏鼠标点击处理

//++++++++++++++++++++++++++++++++++
// 游戏主函数
//----------------------------------
INT APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, INT nCmdShow)
{
	/* 1.设计一个窗口类 */

	/* 2.注册窗口类 */

	/* 3.创建窗口 */

	/* 4.更新显示窗口 */

	/* 井字游戏的初始化 */
	TicTacToe_Init(hWnd);

	/* 5.消息循环 */
	MSG msg = { 0 };
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		/* 井字游戏渲染 */
		TicTacToe_Render(hWnd);
	}

	return msg.wParam;
}


//++++++++++++++++++++++++++++++++++
// 窗口消息处理过程
//----------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_PAINT:
		/* 井字游戏渲染 */
		TicTacToe_Render(hWnd);
		break;
	case WM_LBUTTONDOWN:
		/* 井字游戏鼠标点击消息处理 */
		TicTacToe_MouseDown(LOWORD(lParam), HIWORD(lParam));
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return ((LRESULT)0);
}

//++++++++++++++++++++++++++++++++++
// 井字游戏初始化
//----------------------------------
VOID TicTacToe_Init(HWND hWnd)
{
	/* 游戏初始化 */
	g_game.Init(hWnd);
	/* 创建兼容DC和兼容位图 */
	Util::CreateDoubleBuffer(hWnd, g_mdc, g_bitmap);
	::SelectObject(g_mdc, g_bitmap);
}

//++++++++++++++++++++++++++++++++++
// 井字游戏绘制
//----------------------------------
VOID TicTacToe_Render(HWND hWnd)
{
	if (g_mdc == NULL)
		return;

	HDC hdc = ::GetDC(hWnd);
	RECT clientRect;
	::GetClientRect(hWnd, &clientRect);
	int width = clientRect.right - clientRect.left;
	int height = clientRect.bottom - clientRect.top;

	/* 游戏绘制 */
	g_game.Render(g_mdc);

	/* 将兼容DC绘制到设备DC上 */
	::BitBlt(hdc, 0, 0, width, height, g_mdc, 0, 0, SRCCOPY);
	::ReleaseDC(hWnd, hdc);
}

//++++++++++++++++++++++++++++++++++
// 井字游戏鼠标点击
//----------------------------------
VOID TicTacToe_MouseDown(int x, int y)
{
	/* 游戏鼠标事件处理 */
	g_game.MouseDown(x, y);
}

简单讲解上面的程序:

1. 当窗口显示后进行初始化游戏,并且创建兼容DC,在后面绘制使用(TicTacToe_Init)

2. PeekMessage无论是否有消息都返回(有消息返回非0,无消息返回0)(详细见百度百科)

3. 循环进行绘制游戏对象(TicTacToe_Render)

4. 当有鼠标点击消息的时候,将鼠标消息传入游戏中进行处理(TicTacToe_MouseDown)

5. 绘制中的双DC(也就是双缓冲)

貌似上面已经有点多了,所以分两篇文章进行讲解吧~

下篇:Win32 游戏开发:TicTacToe(井字游戏) 下篇

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值