C语言实现贪吃蛇游戏

贪吃蛇游戏分析

贪吃蛇游戏简介

贪吃蛇与扫雷游戏、俄罗斯方块一样,都是久负盛名的小游戏,学会用C语言实现贪吃蛇游戏,有助于我们更好的理解C语言的语法

贪吃蛇所涉及到的技术包含函数、结构体、枚举、指针、Win32API等。

其中除了Win32API之外,其他都是C语言的语法,当然除了这些之外,还包含C语言的其他一些基础语法,这里我们不过多赘述。

Win32API

Windows 这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外, 它同时也是⼀个很⼤的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程序达到开启视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application), 所以便 称之为 Application Programming Interface,简称 API 函数。WIN32 API也就是Microsoft Windows 32位平台的应⽤程序编程接⼝

由于Win32API包含很多的函数,而我们在贪吃蛇游戏实现的过程中,只需要用到Win32API中的部分函数,所以我们只对游戏实现过程中需要用到的Win32API函数进行讲解,其余函数不过多赘述

GetStdHandle

GetStdHandle是⼀个Windows API函数。它⽤于从⼀个特定的标准设备(标准输⼊、标准输出或标准错误)中取得⼀个句柄(⽤来标识不同设备的数值),使⽤这个句柄可以操作设备。

实例:

GetConsoleCursonInfo

检索有关指定控制台屏幕缓冲区的光标⼤⼩和可⻅性的信息。

实例:

CONSOLE_CURSOR_INFO

这个结构体,包含有关控制台光标的信息

  • dwSize,由光标填充的字符单元格的百分⽐。 此值介于1到100之间。 光标外观会变化,范围从完全填充单元格到单元底部的⽔平线条。
  • bVisible,游标的可⻅性。 如果光标可⻅,则此成员为 TRUE。

SetConsoleCursonInfo

设置指定控制台屏幕缓冲区的光标的⼤⼩和可⻅性。

实例:

控制台屏幕上的坐标COORD

COORD 是Windows API中定义的⼀个结构体,表⽰⼀个字符在控制台屏幕幕缓冲区上的坐标,坐标系 (0,0) 的原点位于缓冲区的顶部左侧单元格。

COORD类型的声明:

给坐标赋值:

SetConsoleCursorPosition

设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调⽤SetConsoleCursorPosition函数将光标位置设置到指定的位置

实例:

SetPos:封装⼀个设置光标位置的函数

GetAsyncKeyState

获取按键情况,GetAsyncKeyState的函数原型如下:

将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。

GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬 起;如果最低位被置为1则说明,该按键被按过,否则为0

如果我们要判断⼀个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1.

虚拟键码

游戏界面

初始页面:

功能介绍:

游戏运行界面:

贪吃蛇游戏实现

根据前面对贪吃蛇游戏的分析,我们知道了完成该游戏所需要的C语言技能及相关的Win32API函数,最后也展示了游戏运行过程中的的各种界面,接下来我们将游戏的整体运行分为三个部分(三个函数),分别为游戏初始化、游戏运行、游戏结束

游戏初始化

游戏初始化的主要功能是设置游戏的欢迎界面、对游戏功能进行介绍,创建墙、创建蛇、创建食物

当然在设置前面介绍的功能之前,我们还需要对蛇身结点的结构、蛇的结构、控制台的大小,控制台的标题以及控制台的光标进行设置,如下图:

Welcome()函数

welcome函数主要是对游戏的初始界面进行设置,包含欢迎界面功能介绍,如下图:

运行效果如下:

CreateMap()函数

CreateMap()函数主要是对游戏中的墙体进行绘制,在绘制墙体之前我们还需要移动控制台的光标,由于墙体使用宽字符进行绘制,宽字符占用两个字节的空间,且使用宽字符需要进行本地化,具体实现如下:

效果如下:

CreateSnake()函数

在游戏初始化过程中,我们还需要创建蛇,由于蛇的身体使用宽字符进行绘制,宽字符占用两个字节的空间,所以我们蛇身的x坐标只能为偶数,除此之外还需要对蛇的其他信息进行设置,如图:

//创建蛇
void CreateSnake(pSnake ps)
{
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		pSnakeNode pnextnode = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (pnextnode == NULL)
		{
			perror("CreateSnake>malloc");
			return;
		}
		pnextnode->x = POS_X + 2 * i;
		pnextnode->y = POS_Y;
		pnextnode->next = NULL;

		//头插
		if (ps->_pSnake == NULL)
		{
			ps->_pSnake = pnextnode;
		}
		else
		{
			pnextnode->next = ps->_pSnake;
			ps->_pSnake = pnextnode;
		}
	}

	//打印蛇
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}

	//设置其他信息
	ps->_dir = RIGHT;
	ps->_Food_Weight = 10;
	ps->_score = 0;
	ps->_Sleep_Time = 200;
	ps->_status = OK;

}

实现效果如下:

CreateFood()函数

除了对蛇的身体进行初始化外,还需要创建食物,由于食物是在一个范围内随机生成的,因此还需要使用随机数,同样食物也是使用宽字符,占用两个字节的空间,食物的x坐标也只能为偶数,且食物不能与蛇的身体重合,如图:

//创建食物
void CreateFood(pSnake ps)
{
	int x = 0;
	int y = 0;

again:
	//生成随机坐标
	do
	{
		x = 2 + rand() % 53;
		y = 1 + rand() % 25;

	} while (x % 2 != 0);

	//判断是否与蛇重合
	pSnakeNode cur = ps->_pSnake;
	while (cur) 
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	//创建食物结点
	pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pFood == NULL)
	{
		perror("CreateFood>malloc");
		return;
	}
	pFood->x = x;
	pFood->y = y;

	SetPos(x, y);
	wprintf(L"%lc", FOOD);

	ps->_pFood = pFood;

}

实现效果如下:

游戏运行

游戏的运行包含:计算总得分和当前食物的分数、打印提示信息、检测按键情况、蛇走一步的过程、蛇走一步后的休眠时间等,还需要对蛇当前的状态进行判断,如图:

//游戏运行
void GameRun(pSnake ps)
{
	//打印提示信息
	PrintTip();
	do
	{
		SetPos(62, 10);
		printf("总得分:%d", ps->_score);
		SetPos(62, 11);
		printf("当前食物分数:%2d", ps->_Food_Weight);
		
		//判断按键
		if (KEY_PRESS(VK_UP) && ps->_dir != DOWN)
		{
			ps->_dir = UP;
		}
		else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
		{
			ps->_dir = DOWN;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
		{
			ps->_dir = LEFT;
		}
		else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT)
		{
			ps->_dir = RIGHT;
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			//退出游戏
			ps->_status = END_NORMAL;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			//暂停
			Pause();
		}
		else if (KEY_PRESS(VK_F3))
		{
			//加速
			if (ps->_Sleep_Time >= 80)
			{
				ps->_Sleep_Time -= 30;
				ps->_Food_Weight += 2;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			//减速
			if (ps->_Food_Weight > 2)
			{
				ps->_Sleep_Time += 30;
				ps->_Food_Weight -= 2;
			}
		}

		//走一步
		SnakeMove(ps);
		//休息一下
		Sleep(ps->_Sleep_Time);


	} while (ps->_status == OK);
}

检测按键:

暂停:

PrintTip()函数

该函数用来打印提示信息,如图:

效果如下:

SnakeMove()函数

该函数是蛇走一步的过程,需要创建下一个结点,判断当前按键的方向,设置下一个结点的x坐标和y坐标,判断下一个结点是不是食物,若是食物就吃掉食物,若不是食物就头插下一个结点,然后将最后一个结点打印成空格并释放掉,最后还要判断蛇是否撞墙或者撞到自己,如图:

//走一步
void SnakeMove(pSnake ps)
{
	//为下一个结点分配内存
	pSnakeNode pnextnode = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pnextnode == NULL)
	{
		perror("SnakeMove>malloc");
		return;
	}

	switch (ps->_dir)
	{
	case UP:
		pnextnode->x = ps->_pSnake->x;
		pnextnode->y = ps->_pSnake->y - 1;
		break;
	case DOWN:
		pnextnode->x = ps->_pSnake->x;
		pnextnode->y = ps->_pSnake->y + 1;
		break;
	case LEFT:
		pnextnode->x = ps->_pSnake->x - 2;
		pnextnode->y = ps->_pSnake->y;
		break;
	case RIGHT:
		pnextnode->x = ps->_pSnake->x + 2;
		pnextnode->y = ps->_pSnake->y;
		break;
	}

	//判断下一个结点是否是食物
	if (NextIsFood(pnextnode,ps))
	{
		//下一步是食物
		EatFood(pnextnode, ps);
	}
	else
	{
		//下一步不是食物
		NoFood(pnextnode, ps);
	}

	//判断是否撞墙
	KILLBYWALL(ps);
	//判断是否撞到自己
	KILLBYSELF(ps);
}

NextIsFood()函数

该函数用来判断下一节点是否为食物,是食物返回1,不是食物返回0,如图:

EatFood()函数

该函数用来吃掉食物,即将下一个结点头插到蛇身中并打印蛇身,如图:

NoFood()函数

如果下一个结点不是食物,就使用该函数,即头插下一个结点,然后将最后一个结点打印成空格并释放掉,如图:

KILLBYWALL()函数

该函数用来判断蛇是否撞到墙,如果撞到墙,就修改蛇的状态,如图:

KILLBYSELF()函数

该函数用来判断蛇是否撞到自己,如果撞到自己,就修改蛇的状态,如图:

游戏结束

当游戏运行结束后,我们就需要进行一些善后工作,我们可以根据蛇的状态判断游戏是怎样退出的,比如撞到墙、撞到自己或者主动退出,但是无论是以何种方式退出游戏的,最后都要把动态分配的空间释放掉,如图:

贪吃蛇游戏最终代码

头文件Snake.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <stdbool.h>
#include <locale.h>
#include <time.h>

#define POS_X 24
#define POS_Y 5


#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'


//蛇的方向
enum DIRECTION
{
	UP,
	DOWN,
	LEFT,
	RIGHT
};


//蛇的状态
enum STATUS
{
	OK,
	KILL_BY_WALL,
	KILL_BY_SELF,
	END_NORMAL
};


//创建蛇身结点的结构
//坐标+指向下一个结点的指针
typedef struct SnakeNode
{
	int x;
	int y;
	struct SnakeNode* next;
}SnakeNode, * pSnakeNode;


//蛇的结构
typedef struct Snake
{
	pSnakeNode _pSnake;
	pSnakeNode _pFood;
	int _score;
	int _Food_Weight;
	int _Sleep_Time;
	enum DIREWCTION _dir;
	enum STATUS _status;
}Snake, * pSnake;


//游戏初始化
void GameInit(pSnake ps);

//欢迎界面
void Welcome();

//移动光标
void SetPos(short x, short y);

//打印地图
void CreateMap();

//创建蛇
void CreateSnake(pSnake ps);

//创建食物
void CreateFood(pSnake ps);

//游戏运行
void GameRun(pSnake ps);

//打印提示信息
void PrintTip();

//暂停
void Pause();

//走一步
void SnakeMove(pSnake ps);

//判断下一个结点是否是食物
int NextIsFood(pSnakeNode pn, pSnake ps);

//下一步是食物
void EatFood(pSnakeNode pn, pSnake ps);

//下一步不是食物
void NoFood(pSnakeNode pn, pSnake ps);

//判断是否撞墙
void KILLBYWALL(pSnake ps);

//判断是否撞到自己
void KILLBYSELF(pSnake ps);


//游戏结束-善后工作
void GameEnd(pSnake ps);

源文件Snake.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Snake.h"

//移动光标
void SetPos(short x, short y)
{
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(houtput, pos);
}


//欢迎界面
void Welcome()
{
	SetPos(35, 14);
	printf("欢迎来到贪吃蛇小游戏");
	SetPos(38, 24);
	system("pause");
	system("cls");

	SetPos(28, 14);
	printf("用↑.↓.←.→分别控制蛇的移动,F3为加速,F4为减速");
	SetPos(35, 15);
	printf("加速将能得到更高的分数");
	SetPos(38, 24);
	system("pause");
	system("cls");
}


//打印地图
void CreateMap()
{
	int i = 0;
	//上
	for (i = 0; i < 29; i++)
	{
		wprintf(L"%lc", WALL);
	}

	//下
	SetPos(0, 26);
	for (i = 0; i < 29; i++)
	{
		wprintf(L"%lc", WALL);
	}

	//左
	for (i = 1; i <= 25; i++)
	{
		SetPos(0, i);
		wprintf(L"%lc", WALL);
	}

	//右
	for (i = 1; i <= 25; i++)
	{
		SetPos(56, i);
		wprintf(L"%lc", WALL);
	}
}


//创建蛇
void CreateSnake(pSnake ps)
{
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		pSnakeNode pnextnode = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (pnextnode == NULL)
		{
			perror("CreateSnake>malloc");
			return;
		}
		pnextnode->x = POS_X + 2 * i;
		pnextnode->y = POS_Y;
		pnextnode->next = NULL;

		//头插
		if (ps->_pSnake == NULL)
		{
			ps->_pSnake = pnextnode;
		}
		else
		{
			pnextnode->next = ps->_pSnake;
			ps->_pSnake = pnextnode;
		}
	}

	//打印蛇
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}

	//设置其他信息
	ps->_dir = RIGHT;
	ps->_Food_Weight = 10;
	ps->_score = 0;
	ps->_Sleep_Time = 200;
	ps->_status = OK;

}


//创建食物
void CreateFood(pSnake ps)
{
	int x = 0;
	int y = 0;

again:
	//生成随机坐标
	do
	{
		x = 2 + rand() % 53;
		y = 1 + rand() % 25;

	} while (x % 2 != 0);

	//判断是否与蛇重合
	pSnakeNode cur = ps->_pSnake;
	while (cur) 
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	//创建食物结点
	pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pFood == NULL)
	{
		perror("CreateFood>malloc");
		return;
	}
	pFood->x = x;
	pFood->y = y;

	SetPos(x, y);
	wprintf(L"%lc", FOOD);

	ps->_pFood = pFood;

}



//游戏初始化
void GameInit(pSnake ps)
{
	//设置窗口
	system("mode con cols=100 lines=32");
	system("title 贪吃蛇");
	//隐藏光标
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cursor_info;
	GetConsoleCursorInfo(houtput, &cursor_info);
	cursor_info.bVisible = false;
	SetConsoleCursorInfo(houtput, &cursor_info);
	
	//欢迎界面
	Welcome();

	//打印地图
	CreateMap();

	//创建蛇
	CreateSnake(ps);

	//创建食物
	CreateFood(ps);

}


//打印提示信息
void PrintTip()
{
	SetPos(62, 15);
	printf("不能穿墙,不能咬到自己");
	SetPos(62, 16);
	printf("用↑.↓.←.→分别控制蛇的移动");
	SetPos(62, 17);
	printf("F3为加速,F4为减速");
	SetPos(62, 18);
	printf("按ESC退出游戏,按space暂停游戏");

}

#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&1)?1:0)


//暂停
void Pause()
{
	while (1)
	{
		Sleep(200);
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
	}
}


//判断下一个结点是否是食物
int NextIsFood(pSnakeNode pn, pSnake ps)
{
	if (pn->x == ps->_pFood->x && pn->y == ps->_pFood->y)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}


//下一步是食物
void EatFood(pSnakeNode pn, pSnake ps)
{
	//头插
	ps->_pFood->next = ps->_pSnake;
	ps->_pSnake = ps->_pFood;

	//释放下一个结点
	free(pn);
	pn = NULL;

	//打印蛇
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}

	//加分数
	ps->_score += ps->_Food_Weight;

	//重新创建食物
	CreateFood(ps);
}


//下一步不是食物
void NoFood(pSnakeNode pn, pSnake ps)
{
	//头插
	pn->next = ps->_pSnake;
	ps->_pSnake = pn;

	//打印前面的结点,将最后一个结点释放掉
	pSnakeNode cur = ps->_pSnake;
	while (cur->next->next != NULL)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	SetPos(cur->x, cur->y);
	wprintf(L"%lc", BODY);

	//将最后一个结点打印成空格
	SetPos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;

}

//判断是否撞墙
void KILLBYWALL(pSnake ps)
{
	if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56 || ps->_pSnake->y == 0 || ps->_pSnake->y == 26)
	{
		ps->_status = KILL_BY_WALL;
	}
}

//判断是否撞到自己
void KILLBYSELF(pSnake ps)
{
	pSnakeNode cur = ps->_pSnake->next;
	while (cur)
	{
		if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y)
		{
			ps->_status = KILL_BY_SELF;
		}
		cur = cur->next;
	}
}



//走一步
void SnakeMove(pSnake ps)
{
	//为下一个结点分配内存
	pSnakeNode pnextnode = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pnextnode == NULL)
	{
		perror("SnakeMove>malloc");
		return;
	}

	switch (ps->_dir)
	{
	case UP:
		pnextnode->x = ps->_pSnake->x;
		pnextnode->y = ps->_pSnake->y - 1;
		break;
	case DOWN:
		pnextnode->x = ps->_pSnake->x;
		pnextnode->y = ps->_pSnake->y + 1;
		break;
	case LEFT:
		pnextnode->x = ps->_pSnake->x - 2;
		pnextnode->y = ps->_pSnake->y;
		break;
	case RIGHT:
		pnextnode->x = ps->_pSnake->x + 2;
		pnextnode->y = ps->_pSnake->y;
		break;
	}

	//判断下一个结点是否是食物
	if (NextIsFood(pnextnode,ps))
	{
		//下一步是食物
		EatFood(pnextnode, ps);
	}
	else
	{
		//下一步不是食物
		NoFood(pnextnode, ps);
	}

	//判断是否撞墙
	KILLBYWALL(ps);
	//判断是否撞到自己
	KILLBYSELF(ps);
}


//游戏运行
void GameRun(pSnake ps)
{
	//打印提示信息
	PrintTip();
	do
	{
		SetPos(62, 10);
		printf("总得分:%d", ps->_score);
		SetPos(62, 11);
		printf("当前食物分数:%2d", ps->_Food_Weight);
		
		//判断按键
		if (KEY_PRESS(VK_UP) && ps->_dir != DOWN)
		{
			ps->_dir = UP;
		}
		else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
		{
			ps->_dir = DOWN;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
		{
			ps->_dir = LEFT;
		}
		else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT)
		{
			ps->_dir = RIGHT;
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			//退出游戏
			ps->_status = END_NORMAL;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			//暂停
			Pause();
		}
		else if (KEY_PRESS(VK_F3))
		{
			//加速
			if (ps->_Sleep_Time >= 80)
			{
				ps->_Sleep_Time -= 30;
				ps->_Food_Weight += 2;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			//减速
			if (ps->_Food_Weight > 2)
			{
				ps->_Sleep_Time += 30;
				ps->_Food_Weight -= 2;
			}
		}

		//走一步
		SnakeMove(ps);
		//休息一下
		Sleep(ps->_Sleep_Time);


	} while (ps->_status == OK);
}


//游戏结束-善后工作
void GameEnd(pSnake ps)
{
	SetPos(22, 12);
	switch (ps->_status)
	{
	case END_NORMAL:
		printf("您主动退出,游戏结束!");
		break;
	case KILL_BY_WALL:
		printf("您撞到墙,游戏结束!");
		break;
	case KILL_BY_SELF:
		printf("您撞到自己,游戏结束!");
		break;
	}

	//释放蛇身
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		pSnakeNode next = cur->next;
		free(cur);
		cur = next;
	}

}

测试文件test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Snake.h"

void test()
{
	int ch = 0;
	do
	{
		system("cls");
		//创建蛇
		Snake snake = { 0 };

		//游戏初始化
		GameInit(&snake);

		//游戏运行
		GameRun(&snake);

		//游戏结束-善后工作
		GameEnd(&snake);

		SetPos(22, 13);
		printf("您是否还要继续(Y/N):");
		ch = getchar();
		while (getchar() != '\n');

	} while (ch == 'Y' || ch == 'y');
	SetPos(0, 27);
}

int main()
{
	//本地化
	setlocale(LC_ALL, "");

	//创建随机数
	srand((unsigned int)time(NULL));

	test();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>