2

C++入门——实现十步万度游戏

 2 years ago
source link: https://blog.csdn.net/beilizhang/article/details/120614399
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
  1. 《C和C++游戏趣味编程》 童晶

十步万度游戏

用鼠标点击任意一个小圆圈,其指针顺时针旋转90度,后续被指向的圆圈指针也依次旋转,所有圆圈的旋转度数累积。玩家点击10次,尝试得到尽量高的旋转度数
在这里插入图片描述

绘制圆圈和指针

定义一个结构体Round,用于保存圆圈的信息,成员变量有圆圈的圆心坐标、半径和角度。进一步,定义一个Round类型的二维数组,保存所有圆圈的信息

#include <graphics.h>
#include <conio.h>
#include <math.h>
#define PI 3.14159

struct Round        // 定义结构体,用来表示带角度指示的小圆圈
{
	float x, y;     // 圆心坐标
	float r;        // 圆圈半径
	int angleNum;   // 对应的角度,取0、1、2、3。表示乘以PI/2后对应的4个角度值
};

// 全局变量定义
Round rounds[5][5];

void startup()      // 初始化函数
{
	initgraph(600, 700);
	setbkcolor(RGB(50, 50, 50));
	setlinestyle(PS_SOLID, 3);    // 设置线条样式、线宽
	cleardevice();
	BeginBatchDraw();

	int i, j;
	for (i = 0; i < 5; i++)                // 初始化5*5个圆圈
	{
		for (j = 0; j < 5; j++)
		{
			rounds[i][j].x = 100 + j * 100;
			rounds[i][j].y = 200 + i * 100;
			rounds[i][j].r = 30;
			rounds[i][j].angleNum = 1;      // 开始都是PI/2
		}
	}
}

void show()          // 绘制函数
{
	int i, j;
	float angle;
	cleardevice();
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 5; j++)
		{
			setlinecolor(RGB(200, 200, 200));// 圆圈的颜色为白灰色
			circle(rounds[i][j].x, rounds[i][j].y, rounds[i][j].r);
			setlinecolor(RGB(255, 0, 0));    // 角度指示线颜色为红色
			angle = rounds[i][j].angleNum * PI / 2;
			line(rounds[i][j].x, rounds[i][j].y, rounds[i][j].x + rounds[i][j].r * cos(-angle), rounds[i][j].y + rounds[i][j].r * sin(-angle));
		}
	}
	FlushBatchDraw();
}

void update()         // 更新函数
{

}

int main()
{
	startup();
	while (1)
	{
		show();
		update();
	}
	return 0;
}

和键盘交互代码结构类似,实现基于鼠标的交互处理:

void update()
{
	ExMessage e;            // 定义鼠标消息
	if (peekmessage(&e))             // 如果有鼠标消息
	{
		if (e.message == WM_LBUTTONDOWN) // 如果点击鼠标左键
		{
			// 执行相应操作
			// m.x为当前鼠标的x坐标,m.y为当前鼠标的y坐标
		}
	}
}

被鼠标点击后旋转

鼠标点击位置的坐标为(m.x, m.y),被点击的小圆圈在二维数组rounds中的行、列序号为:

int clicked_i = int(m.y - 150) / 100;
int clicked_j = int(m.x - 50) / 100;

被点击的小圆圈需要顺时针旋转90度,需要将angleNum值依次减小:

rounds[clicked_i][clicked_j].angleNum -= 1;
if (rounds[clicked_i][clicked_j].angleNum < 0)
{
	rounds[clicked_i][clicked_j].angleNum = 3;
}

将小圆圈顺时针旋转的功能封装在rotateRound()中:

void rotateRound(int i, int j)
{
	rounds[i][j].angleNum -= 1;
	if (rounds[i][j].angleNum < 0)
	{
		rounds[i][j].angleNum = 3;
	}
}
void update()         // 更新函数
{
	ExMessage e;
	if (peekmessage(&e))
	{
		if (e.message == WM_LBUTTONDOWN)              // 如果点击鼠标左键
		{
			int clicked_i = int(e.y - 150) / 100;  // 获取当前点击圆圈的序号
			int clicked_j = int(e.x - 50) / 100;
			rotateRound(clicked_i, clicked_j);
			show();
		}
	}
}

旋转的传播

当鼠标点击一个小圆圈时,小圆圈顺时针旋转90度,然后其指向的下一个圆圈继续旋转90度,如此迭代,直到不指向任何小圆圈为止

首先,定义一维数组indexes,存储被鼠标点中的小圆圈在二维数组rounds中的行列序号:

int index[2] = {clicked_i, clicked_j};

定义函数int GetNextIndexes(int indexes[2]),根据当前小圆圈的序号indexes[0]、indexes[1]和当前小圆圈的角度angleNum,首先求出其指向小圆圈的序号。如果指向的小圆圈超出边界,函数返回0;如果指向一个有效的小圆圈,就把其序号更新到数组indexes中,函数返回1

int GetNextIndexes(int indexes[2])
{
	int i = indexes[0];
	int j = indexes[1];

	// 根据当前圆圈的角度,获得下一个小圆圈的序号
	if (rounds[i][j].angleNum == 0)                // 指向右边的
	{
		j++;
	}
	else if (rounds[i][j].angleNum == 3)           // 指向下边
	{
		i++;
	}
	else if (rounds[i][j].angleNum == 2)           // 指向左边
	{
		j--;
	}
	else if (rounds[i][j].angleNum == 1)           // 指向上边
	{
		i--;
	}

	indexes[0] = i;
	indexes[1] = j;

	if (i >= 0 && i < 5 && j >= 0 && j < 5)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

定义全局变量step和score记录剩下的操作步数和一共旋转的度数:

int step;
int score;

在show()函数中输出相关的文字信息:

void show()          // 绘制函数
{
	TCHAR s[20];                             // 要输出的字符串
	setbkmode(TRANSPARENT);                  // 透明显示文字
	swprintf_s(s, _T("%d 步   %d 度"), step, score); // 把整数转换为字符串
	settextstyle(50, 0, _T("宋体"));
	outtextxy(150, 30, s);                          // 在xy位置输出字符串文字
	settextstyle(20, 0, _T("宋体"));
	outtextxy(15, 100, _T("点击一个圆圈 其指针顺时针旋转90度之后 指向的指针依次旋转"));
	FlushBatchDraw();
	FlushBatchDraw();
}

每旋转一次,得分增加90度:

void rotateRound(int i, int j)
{
	score += 90;
}

鼠标每操作一次,step减1:

if (e.message == WM_LBUTTONDOWN && step > 0)
{
	step--;
}
#include <graphics.h>
#include <conio.h>
#include <math.h>
#define PI 3.14159

struct Round        // 定义结构体,用来表示带角度指示的小圆圈
{
	float x, y;     // 圆心坐标
	float r;        // 圆圈半径
	int angleNum;   // 对应的角度,取0、1、2、3。表示乘以PI/2后对应的4个角度值
};

// 全局变量定义
Round rounds[5][5];
int step;
int score;

void startup()      // 初始化函数
{
	initgraph(600, 700);
	setbkcolor(RGB(50, 50, 50));
	setlinestyle(PS_SOLID, 3);    // 设置线条样式、线宽
	cleardevice();
	BeginBatchDraw();
	step = 10;
	score = 0;
	int i, j;
	for (i = 0; i < 5; i++)                // 初始化5*5个圆圈
	{
		for (j = 0; j < 5; j++)
		{
			rounds[i][j].x = 100 + j * 100;
			rounds[i][j].y = 200 + i * 100;
			rounds[i][j].r = 30;
			rounds[i][j].angleNum = 1;      // 开始都是PI/2
		}
	}
}

void show()          // 绘制函数
{
	int i, j;
	float angle;
	cleardevice();
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 5; j++)
		{
			setlinecolor(RGB(200, 200, 200));// 圆圈的颜色为白灰色
			circle(rounds[i][j].x, rounds[i][j].y, rounds[i][j].r);
			setlinecolor(RGB(255, 0, 0));    // 角度指示线颜色为红色
			angle = rounds[i][j].angleNum * PI / 2;
			line(rounds[i][j].x, rounds[i][j].y, rounds[i][j].x + rounds[i][j].r * cos(-angle), rounds[i][j].y + rounds[i][j].r * sin(-angle));
		}
	}
	TCHAR s[20];                             // 要输出的字符串
	setbkmode(TRANSPARENT);                  // 透明显示文字
	swprintf_s(s, _T("%d 步   %d 度"), step, score); // 把整数转换为字符串
	settextstyle(50, 0, _T("宋体"));
	outtextxy(150, 30, s);                          // 在xy位置输出字符串文字
	settextstyle(20, 0, _T("宋体"));
	outtextxy(15, 100, _T("点击一个圆圈 其指针顺时针旋转90度之后 指向的指针依次旋转"));
	FlushBatchDraw();
}

void rotateRound(int i, int j)
{
	rounds[i][j].angleNum -= 1;
	if (rounds[i][j].angleNum < 0)
	{
		rounds[i][j].angleNum = 3;
	}
	score += 90;
}

int GetNextIndexes(int indexes[2])
{
	int i = indexes[0];
	int j = indexes[1];

	// 根据当前圆圈的角度,获得下一个小圆圈的序号
	if (rounds[i][j].angleNum == 0)                // 指向右边的
	{
		j++;
	}
	else if (rounds[i][j].angleNum == 3)           // 指向下边
	{
		i++;
	}
	else if (rounds[i][j].angleNum == 2)           // 指向左边
	{
		j--;
	}
	else if (rounds[i][j].angleNum == 1)           // 指向上边
	{
		i--;
	}

	indexes[0] = i;
	indexes[1] = j;

	if (i >= 0 && i < 5 && j >= 0 && j < 5)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

void update()         // 更新函数
{
	ExMessage e;
	if (peekmessage(&e))
	{
		if (e.message == WM_LBUTTONDOWN && step > 0)              // 如果点击鼠标左键
		{
			int clicked_i = int(e.y - 150) / 100;              // 获取当前点击圆圈的序号
			int clicked_j = int(e.x - 50) / 100;
			rotateRound(clicked_i, clicked_j);
			show();
			Sleep(300);

			int indexes[2] = { clicked_i, clicked_j };         // 存储当前点击圆圈的序号
			while (GetNextIndexes(indexes))                    // 依次获取指向的下一个圆圈
			{
				rotateRound(indexes[0], indexes[1]);
				show();
				Sleep(300);
			}
		}
	}
}

int main()
{
	startup();
	while (1)
	{
		show();
		update();
	}
	return 0;
}

在这里插入图片描述


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK