数据结构上机实验2——树——二叉树着色游戏

利用easyx库设计并实现一个二叉树着色游戏
在这里插入图片描述
Tree.h

#ifndef TREE_H
#include <graphics.h>              // 引用图形库头文件
#include <easyx.h>
#include <conio.h>
#include <math.h>
#define MaxSize 50
#define LENGTH 1080
#define WIDTH 720
#define LINELENGTH floor(60*sqrt(2))
#define RADIUS floor(10*sqrt(2))
enum NodeColor { white, red, blue };
enum Direction { LEFT, RIGHT };
enum Players { one, two };
int x_tree = 540, y_tree = 60;
typedef struct PSTreeNode
{
	int val;            //值
	int color;          //颜色
	PSTreeNode* parent; //双亲结点
	PSTreeNode* lchild; //左孩子结点
	PSTreeNode* rchild; //右孩子结点
	int x;     //圆心x坐标
	int y;     //圆心y坐标
}PSTree;
//画树枝
void DrawLine(int xi, int yi, int xe, int ye, int flag) {
	int x1, x2;
	int y1 = yi + 10;
	int y2 = ye - 10;
	if (flag == LEFT) {
		x1 = xi - 10;
		x2 = xe + 10;
	}
	else if (flag == RIGHT) {
		x1 = xi + 10;
		x2 = xe - 10;
	}
	line(x1, y1, x2, y2);
}
//计算下一个结点圆心坐标
int* CircleCenter(int flag, int x, int y) {
	int a[2];
	static int n = 0;  //记录结点数
	static int h = 1;  //记录第几层
	static int xchange = 400;  //记录横坐标差值
	++n;
	if (n == pow(2, h - 1)) {
		h++;
		n = 0;
		xchange /= 2;
	}
	if (flag == LEFT) {
		a[0] = x - xchange;
		a[1] = y + 80;
	}
	else if (flag == RIGHT) {
		a[0] = x + xchange;
		a[1] = y + 80;
	}
	return a;
}
//点击的位置在圆内   x,y鼠标点击的坐标
bool InCircle(int x, int y, int xc, int yc) {
	if ((pow((xc - x), 2) + pow((yc - y), 2)) <= pow(RADIUS, 2))
	{
		return true;
	}
	else
		return false;
}
#endif // !TREE_H

Queue.h

#ifndef QUEUE_H
#include <stdio.h>
#include "tree.h"
//#define MaxSize 50
//typedef struct qnode
//{
//    PSTree* data;
//    struct qnode* next;
//}QNode;
typedef struct
{
    PSTree* data[MaxSize];
    int front, rear;
}LiQueue;
void InitQueue(LiQueue*& q)
{
    q = (LiQueue*)malloc(sizeof(LiQueue));
    q->front = q->rear = 0;
}
void DestroyQueue(LiQueue*& q)
{
    free(q);
}
bool QueueEmpty(LiQueue* q)
{
    return (q->rear == q->front);
}
bool enQueue(LiQueue*& q, PSTree* e)
{
    if ((q->rear + 1) % MaxSize == q->front) {
        return false;
    }
    q->rear = (q->rear + 1) % MaxSize;
    q->data[q->rear] = e;
    return true;
}
bool deQueue(LiQueue*& q, PSTree*& e)
{
    if (q->front == q->rear) {
        return false;
    }
    q->front = (q->front + 1) % MaxSize;
    e = q->data[q->front];
    return true;
}
#endif // !QUEUE_H

Best.h

#ifndef BEST_H
#include "queue.h"
//打印一号玩家胜率最大的点
void PlayerOne(int n, PSTree* tree, int& oneWin)
{
	int i = 1;
	PSTree* p = tree;
	while (p->rchild != NULL)
	{
		i++;
		p = p->rchild;
	}
	if (pow(2, i) - 1 == n)
	{
		outtextxy(30, 60, _T("1为player1胜率较大的位置"));
		oneWin = 1;
	}
	else if ((pow(2, i + 1) - 2 == n) && (pow(2, i) == n))
	{
		outtextxy(30, 60, _T("1或2为player1胜率较大的位置"));
	}
	else
	{
		outtextxy(30, 60, _T("2为player1胜率较大的位置"));
		oneWin = 2;
	}
	return;
}
//打印二号玩家胜率最大的点
void PlayerTwo(int n, PSTree* tree, int oneWin)
{
	int m, twoWin;
	PSTree* p = tree;
	LiQueue* qu;
	InitQueue(qu);
	enQueue(qu, p);
	while (!QueueEmpty(qu))
	{
		deQueue(qu, p);
		if (p->color == red)
		{
			m = p->val;
			break;
		}
		if (p->lchild != NULL)
		{
			enQueue(qu, p->lchild);
		}
		if (p->rchild != NULL)
		{
			enQueue(qu, p->rchild);
		}
	}
	if (m == oneWin)
	{
		outtextxy(30, 90, _T("player2无法获胜"));
		return;
	}
	if (p->parent != NULL)             //一号玩家不是根节点
	{
		twoWin = p->parent->val;
	}
	else                                           //一号玩家是根节点
	{
		twoWin = 2;
	}
	char c = '0' + twoWin;
	outtextxy(30, 90, c);
	outtextxy(40, 90, _T("为player2胜率较大的位置"));
	return;
}
#endif // !BEST_H

Game.h

#ifndef GAME_H
#include <windows.h>				//用到了定时函数sleep()
#include "best.h"
int whitecount = 0;     //白色结点个数
int player;             //当前玩家
int count = 0;          //第一次和第二次着色
bool playerone = true;  //玩家1有可走结点 
bool playertwo = true;  //玩家2有可走结点
int rec[] = { 940,30,1040,80 };//跳过按钮
//建立一个结点
PSTree* CreateNode(PSTree* parent, int x) {
    PSTree* tree = (PSTree*)malloc(sizeof(PSTree));
    tree->val = x;
    tree->lchild = NULL;
    tree->rchild = NULL;
    tree->parent = parent;
    tree->color = white;
    return tree;
}
//创建一棵树
PSTree* CreateTree(int root[], int n) {
    settextcolor(BLACK);
    setlinecolor(BLACK);
    outtextxy(30, 30, _T("二叉树着色游戏"));
    LiQueue* treeQueue;
    int i = 2, count = 1;
    InitQueue(treeQueue);
    PSTree* tree;
    PSTree* node = (PSTree*)malloc(sizeof(PSTree));
    //创建根节点
    tree = CreateNode(NULL, root[1]);
    tree->x = x_tree;
    tree->y = y_tree;
    node = tree;
    circle(node->x, node->y, RADIUS);
    enQueue(treeQueue, node);
    while (!QueueEmpty(treeQueue)) {
        deQueue(treeQueue, node);
        if (node->lchild == NULL) {
            PSTree* treeNode = CreateNode(node, root[i]);
            node->lchild = treeNode;
            int* xy = CircleCenter(LEFT, node->x, node->y);
            treeNode->x = xy[0];
            treeNode->y = xy[1];
            DrawLine(node->x, node->y, treeNode->x, treeNode->y, LEFT);
            circle(treeNode->x, treeNode->y, RADIUS);
            enQueue(treeQueue, treeNode);
            count++;
            i++;
            if (count == n || i > n) {
                break;
            }
        }
        if (node->rchild == NULL) {
            PSTree* treeNode = CreateNode(node, root[i]);
            node->rchild = treeNode;
            int* xy = CircleCenter(RIGHT, node->x, node->y);
            treeNode->x = xy[0];
            treeNode->y = xy[1];
            DrawLine(node->x, node->y, treeNode->x, treeNode->y, RIGHT);
            circle(treeNode->x, treeNode->y, RADIUS);
            enQueue(treeQueue, treeNode);
            count++;
            i++;
            if (count == n || i > n) {
                break;
            }
        }
    }
    DestroyQueue(treeQueue);
    return tree;
}
//游戏结束条件  所有结点都不是白色
bool GameOver(PSTree* tree, int n) {
    if (tree != NULL) {
        GameOver(tree->lchild, n);
        GameOver(tree->rchild, n);
        if (tree->color == white) {
            ++whitecount;
        }
        //有是白色的结点,说明游戏未结束
        if (whitecount != 0) {
            return false;
        }
        else {
            return true;
        }
    }
}
//跳过按钮
bool pass(int x,int y) {
    if (x > rec[0] && x<rec[2] && y>rec[1] && y < rec[3]) {
        if (player == one) {
            player = two;
            playerone = false;
            outtextxy(920, 100, _T("1号玩家无可走结点"));
            outtextxy(930, 125, _T("已切换到2号玩家"));
            return false;
        }
        else if (player == two) {
            player = one;
            playertwo = false;
            outtextxy(920, 100, _T("2号玩家无可走结点"));
            outtextxy(930, 125, _T("已切换到1号玩家"));
            return false;
        }
    }
    else {
        return false;
    }
}
//变色判断条件
void judge(PSTree* tree, int x, int y, PSTree* root, bool firORsec = false) {
    if (playerone && playertwo && pass(x, y)) {
        return;
    }
    if (!firORsec) {
        if (player == one
            && tree->color == white
            && InCircle(x, y, tree->x, tree->y) ) {
            if ((tree->parent == NULL
                && tree->lchild != NULL
                && tree->rchild != NULL
                && (tree->lchild->color == red || tree->rchild->color == red)
                && playerone)
                || (tree->parent != NULL
                    && tree->lchild == NULL
                    && tree->rchild == NULL
                    && tree->parent->color == red
                    && playerone)
                || (tree->parent != NULL
                    && tree->lchild != NULL
                    && tree->rchild != NULL
                    && (tree->lchild->color == red || tree->rchild->color == red || tree->parent->color == red)
                    && playerone)) {
                tree->color = red;
                clearcircle(tree->x, tree->y, RADIUS);
                setlinecolor(BLACK);
                setfillcolor(RED);
                circle(tree->x, tree->y, RADIUS);
                fillcircle(tree->x, tree->y, RADIUS);
                if (playertwo) {
                    player = two;
                }
            }
        }
        else if (player == two
            && tree->color == white
            && InCircle(x, y, tree->x, tree->y)) {
            if ((tree->parent == NULL
                && tree->lchild != NULL
                && tree->rchild != NULL
                && (tree->lchild->color == blue || tree->rchild->color == blue)
                && playertwo)
                || (tree->parent != NULL
                    && tree->lchild == NULL
                    && tree->rchild == NULL
                    && tree->parent->color == blue
                    && playertwo)
                || (tree->parent != NULL
                    && tree->lchild != NULL
                    && tree->rchild != NULL
                    && (tree->lchild->color == blue || tree->rchild->color == blue || tree->parent->color == blue)
                    && playertwo)) {
                tree->color = blue;
                clearcircle(tree->x, tree->y, RADIUS);
                setlinecolor(BLACK);
                setfillcolor(BLUE);
                circle(tree->x, tree->y, RADIUS);
                fillcircle(tree->x, tree->y, RADIUS);
                if (playerone) {
                    player = one;
                }
            }
        }
    }
    //第一次或第二次填充颜色时
    else {
        if (tree->color == white
            && InCircle(x, y, tree->x, tree->y)
            ) {
            if (count == 0) {
                tree->color = red;
                clearcircle(tree->x, tree->y, RADIUS);
                setlinecolor(BLACK);
                setfillcolor(RED);
                circle(tree->x, tree->y, RADIUS);
                fillcircle(tree->x, tree->y, RADIUS);
                ++count;
                player = two;
                return;
            }
            else if (count == 1) {
                tree->color = blue;
                clearcircle(tree->x, tree->y, RADIUS);
                setlinecolor(BLACK);
                setfillcolor(BLUE);
                circle(tree->x, tree->y, RADIUS);
                fillcircle(tree->x, tree->y, RADIUS);
                ++count;
                player = one;
                return;
            }
        }
    }
}
int WinPlayer(PSTree* root) {
    static int oneCount = 0;
    static int twoCount = 0;
    if (root != NULL) {
        WinPlayer(root->lchild);
        WinPlayer(root->rchild);
        if (root->color == red) {
            oneCount++;
        }
        else if (root->color == blue) {
            twoCount++;
        }
    }
    return (oneCount > twoCount) ? one : two;
}
void MouseClick(PSTree* root, int x, int y, int n, bool firORsec =false) {
    LiQueue* qu;
    InitQueue(qu);
    int count = 1;
    PSTree* node = (PSTree*)malloc(sizeof(PSTree));
    node = root;
    enQueue(qu, node);
    judge(node, x, y, root, firORsec);
    while (!QueueEmpty(qu)) {
        deQueue(qu, node);
        if (node->lchild != NULL) {
            enQueue(qu, node->lchild);
            judge(node->lchild, x, y, root, firORsec);
            count++;
            if (count == n) {
                break;
            }
        }
        if (node->rchild != NULL) {
            enQueue(qu, node->rchild);
            judge(node->rchild, x, y, root, firORsec);
            count++;
            if (count == n) {
                break;
            }
        }
    }
    DestroyQueue(qu);
}
void GamePlay() {
	initgraph(LENGTH, WIDTH);//初始化窗口(黑屏)
	for (int i = 0; i < 256; i += 5)
	{
		setbkcolor(RGB(i, i, i));//设置背景色,原来默认黑色
		cleardevice();//清屏(取决于背景色)
		Sleep(15);//延时15ms
	}
	int root[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
    player = one;
    int length = sizeof(root) / sizeof(int) - 1;
    bool firORsec = true;
    PSTree* tree = CreateTree(root, length);
    RECT rect = { rec[0], rec[1], rec[2], rec[3] };
    rectangle(rec[0], rec[1], rec[2], rec[3]);
    drawtext(_T("pass"), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    int oneWin = 0;
    PlayerOne(length, tree, oneWin);
    MOUSEMSG m;//鼠标指针
    setrop2(R2_NOTXORPEN);//二元光栅——NOT(屏幕颜色 XOR 当前颜色)
    while (!GameOver(tree, length))
    {
        m = GetMouseMsg();//获取一条鼠标消息
        
        if (m.uMsg == WM_LBUTTONDOWN && firORsec)
        {
            for (int i = 0; i <= 10; i++)
            {
                setlinecolor(RGB(25 * i, 25 * i, 25 * i));//设置圆颜色
                circle(m.x, m.y, 2 * i);
                Sleep(25);//停顿2ms
                circle(m.x, m.y, 2 * i);//抹去刚刚画的圆
            }
            MouseClick(tree, m.x, m.y, length, firORsec);
            if (count == 1) {
                PlayerTwo(length, tree, oneWin);
            }
            //判断是否已经画了两个结点了
            if (count >= 2) {
                firORsec = false;
            }
            FlushMouseMsgBuffer();//清空鼠标消息缓存区
        }
        else if(m.uMsg == WM_LBUTTONDOWN && !firORsec){
            for (int i = 0; i <= 10; i++)
            {
                setlinecolor(RGB(25 * i, 25 * i, 25 * i));//设置圆颜色
                circle(m.x, m.y, 2 * i);
                Sleep(25);//停顿2ms
                circle(m.x, m.y, 2 * i);//抹去刚刚画的圆
            }
            MouseClick(tree, m.x, m.y, length);
            FlushMouseMsgBuffer();//清空鼠标消息缓存区
        }
        whitecount = 0;
    }
    settextcolor(BLACK);
    if (WinPlayer(tree) == one) {
        TCHAR s[] = _T("1号玩家获胜");
        outtextxy(510, 680, s);
    }
    else if (WinPlayer(tree) == two) {
        TCHAR s[] = _T("2号玩家获胜");
        outtextxy(510, 680, s);
    }
	system("pause");//暂停,为了显示
	closegraph();
}
#endif // !GAME_H

main.cpp

#include "game.h"
//完全二叉树   结点个数为奇数
int main()
{
	GamePlay();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值