Laya连线小游戏
Laya连线小游戏

游戏规则
- 通过连接不同颜色的方块来实现连一连
- 连线不可重复,就是一条线不能和另外一条线撞一起
- 最后所有连线要占据整个空间
游戏资源

创建Item

线条可以分为上左下右,通过显示和隐藏达到画线的效果。

譬如item1到item2,通过判断两者posX,posY,item1调用方法showLine(3)显示line3,item2调用方法showLine(1)显示line1。
Item.ts。
import { ui } from "../ui/layaMaxUI";
export class Item extends ui.view.ItemUI{
public colorType:number = 1;//定义线条颜色
public type:number = 0;//类型
public posX:number = 1;//位置x
public posY:number = 1;//位置y
public isLinkList:boolean = false;//是否已经连过了
/* 创建item */
public static createItem():Item{
let item:Item = new Item();
item.line1.visible = false;
item.line2.visible = false;
item.line3.visible = false;
item.line4.visible = false;
return item;
}
/* 设置线条颜色 */
public setLineColor(value:number):void{
this.isLinkList = true;
this.colorType = value;
for(let i:number = 1; i <= 4; i++){
this["line" + i].skin = "res/ui/icon/line_line" + value + ".png";
}
}
/* 设置icon */
public setIcon(value:number):void{
this.type = value;
if(value > 0){
this.icon.skin = "res/ui/icon/line_icon" + value + ".png";
}else{
this.icon.skin = "";
}
}
/* 显示上或下或左或右线条 */
public showLine(value:number):void{
switch(value){
case 1:
this.line1.visible = true;break;
case 2:
this.line2.visible = true;break;
case 3:
this.line3.visible = true;break;
case 4:
this.line4.visible = true;break;
default:
this.line1.visible = false;
this.line2.visible = false;
this.line3.visible = false;
this.line4.visible = false;
this.isLinkList = false;
break;
}
}
}
游戏界面创建

创建GameView.ts,类GameView继承自该界面
import { LinkList } from "../script/LinkList";
import { ui } from "../ui/layaMaxUI";
import { Item } from "./Item";
export class GameView extends ui.dialog.GameUI {
private row:number = 5;//行数
private column:number = 5;//列数
private itemArr:Array<Item> = [];//存放item的数组
private dataArr:Array<number> = [1,0,0,0,3,0,0,2,0,0,1,0,0,3,0,4,0,0,4,2,5,0,0,0,5];
private ITEM_WIDTH:number = 120;//定义item宽
private ITEM_HEIGHT:number = 120;//定义item高
private canDraw:boolean = false;//是否能画线
private tempPoint:Laya.Point = new Laya.Point();
private list1:LinkList = new LinkList();//链表1
private list2:LinkList = new LinkList();//链表2
private list3:LinkList = new LinkList();//链表3
private list4:LinkList = new LinkList();//链表4
private list5:LinkList = new LinkList();//链表5
private currentList:LinkList;
constructor() {
super();
this.init();
}
private init():void{
this.addEvent();
this.initDrawLinePanel();
}
private addEvent():void{
Laya.stage.on(Laya.Event.RESIZE,this,this.onResize);
this.panelNode.on(Laya.Event.MOUSE_DOWN,this,this.onMouseDown);
this.panelNode.on(Laya.Event.MOUSE_MOVE,this,this.onMouseMove);
this.panelNode.on(Laya.Event.MOUSE_OUT,this,this.onMouseOut);
this.panelNode.on(Laya.Event.MOUSE_UP,this,this.onMouseOut);
}
/* 初始化画线面板 */
private initDrawLinePanel():void{
let item:Item;
for(let i:number = 0; i < this.row; i++){
for(let j:number = 0; j < this.column; j++){
item = Item.createItem();
item.pos(j * this.ITEM_WIDTH,i * this.ITEM_HEIGHT);
item.posX = j;
item.posY = i;
item.setIcon(this.dataArr.shift());
this.panelNode.addChild(item);
this.itemArr.push(item);
}
}
let panelWidth:number = this.ITEM_WIDTH * this.column;
let panelHeight:number = this.ITEM_HEIGHT * this.row;
this.panelNode.size(panelWidth,panelHeight);
this.panelNode.x = -0.5 * panelWidth;
this.panelNode.y = -0.5 * panelHeight;
}
/* 鼠标按下 */
private onMouseDown():void{
//全局坐标转为panelNode局部坐标
this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY);
let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint));
let posX:number = Math.floor(point.x / this.ITEM_WIDTH);
let posY:number = Math.floor(point.y / this.ITEM_HEIGHT);
let index:number = posY * this.column + posX;
let item:Item = this.itemArr[index];//拿到对应的item
if(item.type > 0){//点击到有颜色的item
this.canDraw = true;
this.currentList = this["list" + item.type];
this.currentList.clear();
this.currentList.append(item);
}else{//点击到没有颜色的item
if(item.isLinkList){//连过了
this.currentList = this["list" + item.colorType];
let tail:Item = this.currentList.getTail().item;
if(item == item){//判断该item是否属于链表尾节点
this.canDraw = true;
}
}
}
}
/* 鼠标滑动 */
private onMouseMove():void{
if(!this.canDraw) return;
//全局坐标转为panelNode局部坐标
this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY);
let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint));
let posX:number = Math.floor(point.x / this.ITEM_WIDTH);
let posY:number = Math.floor(point.y / this.ITEM_HEIGHT);
let index:number = posY * this.column + posX;
let item:Item = this.itemArr[index];//拿到对应的item
let tail:Item = this.currentList.getTail().item;//链表尾
if((posX == tail.posX && Math.abs(posY - tail.posY) == 1) || (posY == tail.posY && Math.abs(posX - tail.posX) == 1)){//必须与链表尾相邻(上下左右)
if(item.type <= 0 || item.type == tail.colorType){//滑动到没有颜色的节点或者是颜色一样
let position:number = this.currentList.positionOf(item);
if(position < 0){
if(item.isLinkList){//已经在其它链表里了
let list:LinkList = this["list" + item.colorType]
list.slice(list.positionOf(item) - 1);
}
this.currentList.append(item);//添加到链表
this.isGetVictory();//是否通关
if(item.type > 0){
this.canDraw = false;
}
}else{
this.currentList.slice(position);//切割链表
}
}else{
this.canDraw = false;
}
}else{
if(item != this.currentList.getTail().item){//此时滑动到的点不是链表尾,才不能画线(在当前的点滑来滑去还是能画线)
this.canDraw = false;
}
}
}
/* 鼠标松开 */
private onMouseOut():void{
this.canDraw = false;
}
/* 是否通过 */
private isGetVictory():boolean{
let count:number = 0
for(let i:number = 1; i <= 5;i ++){//遍历所有链表,判断链表长度是否等于面板上的方格总数
count += this["list" + i].size()
}
if(count == this.row * this.column){
return true;
}
return false;
}
private onResize():void{
this.height = Laya.stage.height;
this.width = Laya.stage.width;
}
}
通过行数5,列数5创建item,添加到panelNode节点上,初始化画线面板。
/* 初始化画线面板 */ private initDrawLinePanel():void{ let item:Item; for(let i:number = 0; i < this.row; i++){ for(let j:number = 0; j < this.column; j++){ item = Item.createItem(); item.pos(j * this.ITEM_WIDTH,i * this.ITEM_HEIGHT); item.posX = j; item.posY = i; item.setIcon(this.dataArr.shift()); this.panelNode.addChild(item); this.itemArr.push(item); } } let panelWidth:number = this.ITEM_WIDTH * this.column; let panelHeight:number = this.ITEM_HEIGHT * this.row; this.panelNode.size(panelWidth,panelHeight); this.panelNode.x = -0.5 * panelWidth; this.panelNode.y = -0.5 * panelHeight; }
通过鼠标位置,计算出posX,posY,拿到对应的item
鼠标全局位置转为panelNode局部位置,计算出posX,posY,再从itemArr拿到对应的item
this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY); let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint)); let posX:number = Math.floor(point.x / this.ITEM_WIDTH); let posY:number = Math.floor(point.y / this.ITEM_HEIGHT); let index:number = posY * this.column + posX; let item:Item = this.itemArr[index];
鼠标按下
鼠标点击时,有俩种情况,才可以画线

第一种情况,点击到颜色方块

第二种情况,不是点击到 颜色方块,但是点击到连线的末端,这时可以继续连线
/* 鼠标按下 */ private onMouseDown():void{ //全局坐标转为panelNode局部坐标 this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY); let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint)); let posX:number = Math.floor(point.x / this.ITEM_WIDTH); let posY:number = Math.floor(point.y / this.ITEM_HEIGHT); let index:number = posY * this.column + posX; let item:Item = this.itemArr[index];//拿到对应的item if(item.type > 0){//点击到有颜色的item this.canDraw = true; this.currentList = this["list" + item.type]; this.currentList.clear(); this.currentList.append(item); }else{//点击到没有颜色的item if(item.isLinkList){//连过了 this.currentList = this["list" + item.colorType]; let tail:Item = this.currentList.getTail().item; if(item == item){//判断该item是否属于链表尾节点 this.canDraw = true; } } } }
鼠标滑动,连线

连线时,只有跟该线线尾相邻才可以连接

滑到不同颜色节点时断开连接

如果滑动到的已经连接过了,就切割该链表

如果滑动到的节点已经被其它节点连接过了,就切割连接过的链表
/* 鼠标滑动 */ private onMouseMove():void{ if(!this.canDraw) return; //全局坐标转为panelNode局部坐标 this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY); let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint)); let posX:number = Math.floor(point.x / this.ITEM_WIDTH); let posY:number = Math.floor(point.y / this.ITEM_HEIGHT); let index:number = posY * this.column + posX; let item:Item = this.itemArr[index];//拿到对应的item let tail:Item = this.currentList.getTail().item;//链表尾 if((posX == tail.posX && Math.abs(posY - tail.posY) == 1) || (posY == tail.posY && Math.abs(posX - tail.posX) == 1)){//必须与链表尾相邻(上下左右) if(item.type <= 0 || item.type == tail.colorType){//滑动到没有颜色的节点或者是颜色一样 let position:number = this.currentList.positionOf(item); if(position < 0){ if(item.isLinkList){//已经在其它链表里了 let list:LinkList = this["list" + item.colorType] list.slice(list.positionOf(item) - 1); } this.currentList.append(item);//添加到链表 this.isGetVictory();//是否通关 if(item.type > 0){ this.canDraw = false; } }else{ this.currentList.slice(position);//切割链表 } }else{ this.canDraw = false; } }else{ if(item != this.currentList.getTail().item){//此时滑动到的点不是链表尾,才不能画线(在当前的点滑来滑去还是能画线) this.canDraw = false; } } }
判断是否连接完成

只需要遍历所有链表,判断链表长度是否等于面板上的方格总数
/* 是否通过 */ private isGetVictory():boolean{ let count:number = 0 for(let i:number = 1; i <= 5;i ++){//遍历所有链表,判断链表长度是否等于面板上的方格总数 count += this["list" + i].size() } if(count == this.row * this.column){ return true; } return false; }
item链表
LinkList.ts
import { Item } from "../view/Item";
export class Node{
public item:Item;//节点数据
public next:Node = null;//指向下一个节点
constructor(item:Item){
this.item = item;
}
}
export class LinkList{
private head:Node = null;//链表头
private tail:Node = null;//链表尾
private length:number = 0;//链表长度
/* 向链表添加新节点 */
public append(item:Item):void{
let node:Node = new Node(item);
if(this.length <= 0){//如果当前链表为空,则将head,tail指向node
item.setLineColor(item.type);
this.head = node;
this.tail = node;
}else{//否则在链表尾添加新元素
item.setLineColor(this.head.item.colorType);
let prevItem:Item = this.tail.item;
this.tail.next = node;
this.tail = node;
this.setLine(prevItem,this.tail.item);
}
this.length++;//链表长度+1
}
/* 截取链表,包含position */
public slice(position:number):boolean{
if(position < 1 || position > this.length){
return false;
}
console.log(position);
let currentNode:Node = this.head;
let currentPosition:number = 1;
let sliceNode:Node;
let prevNode:Node;
while(currentNode){
if(currentPosition == position - 1){
prevNode = currentNode;
}
else if(currentPosition == position){
this.length = position;
sliceNode = currentNode;
currentNode.item.showLine(0);
currentNode.item.isLinkList = true;
}else if(currentPosition > position){
currentNode.item.showLine(0);
}
currentNode = currentNode.next;
currentPosition++;
}
sliceNode.next = null;
if(prevNode){
this.setLine(prevNode.item,sliceNode.item);
}
this.tail = sliceNode;
}
/* 设置线条 */
private setLine(item1:Item,item2:Item):void{
let prevX:number = item1.posX;
let prevY:number = item1.posY;
let nextX:number = item2.posX;
let nextY:number = item2.posY;
if(prevX == nextX){
if(prevY > nextY){
item1.showLine(1);
item2.showLine(3);
}else{
item1.showLine(3);
item2.showLine(1);
}
}
if(prevY == nextY){
if(prevX > nextX){
item1.showLine(4);
item2.showLine(2);
}else{
item1.showLine(2);
item2.showLine(4);
}
}
}
/* 查找某个元素所在的节点位置 */
public positionOf(item:Item):number{
let currentNode:Node = this.head;
let currentPosition:number = 1;
while(currentNode){
if(currentNode.item == item){
return currentPosition;
}
currentPosition++;
currentNode = currentNode.next;
}
return -1;
}
/* 返回某位置的节点*/
public getNodeAt(position:number):Node{
if(position < 1 || position > this.length){//越界
return null;
}
let currentNode:Node = this.head;
let currentPositon:number = 1;
while(currentPositon < position){//遍历链表,找到节点
currentNode = currentNode.next;
currentPositon++;
}
return currentNode;
}
/* 链表是否为空 */
public isEmpty():boolean{
return this.length == 0;
}
/* 返回链表长度 */
public size():number{
return this.length;
}
/* 返回链表头 */
public getHead():Node{
return this.head;
}
/* 返回链表尾 */
public getTail():Node{
return this.tail;
}
/* 清空链表 */
public clear():void{
let currentNode:Node = this.head;
while(currentNode){
currentNode.item.showLine(0);
currentNode = currentNode.next;
}
this.head = null;
this.tail = null;
this.length = 0;
}
}
设置线条
通过比较链表前后节点的item,显示对应的线条

/* 设置线条 */ private setLine(item1:Item,item2:Item):void{ let prevX:number = item1.posX; let prevY:number = item1.posY; let nextX:number = item2.posX; let nextY:number = item2.posY; if(prevX == nextX){ if(prevY > nextY){ item1.showLine(1); item2.showLine(3); }else{ item1.showLine(3); item2.showLine(1); } } if(prevY == nextY){ if(prevX > nextX){ item1.showLine(4); item2.showLine(2); }else{ item1.showLine(2); item2.showLine(4); } } }
item链表添加节点
需要设置一下当前节点跟上一个节点的线条
/* 向链表添加新节点 */ public append(item:Item):void{ let node:Node = new Node(item); if(this.length <= 0){//如果当前链表为空,则将head,tail指向node item.setLineColor(item.type); this.head = node; this.tail = node; }else{//否则在链表尾添加新元素 item.setLineColor(this.head.item.colorType); let prevItem:Item = this.tail.item; this.tail.next = node; this.tail = node; this.setLine(prevItem,this.tail.item); } this.length++;//链表长度+1 }
item链表截取节点


/* 截取链表,包含position */
public slice(position:number):boolean{ if(position < 1 || position > this.length){ return false; } console.log(position); let currentNode:Node = this.head; let currentPosition:number = 1; let sliceNode:Node; let prevNode:Node; while(currentNode){ if(currentPosition == position - 1){ prevNode = currentNode; } else if(currentPosition == position){ this.length = position; sliceNode = currentNode; currentNode.item.showLine(0); currentNode.item.isLinkList = true; }else if(currentPosition > position){ currentNode.item.showLine(0); } currentNode = currentNode.next; currentPosition++; } sliceNode.next = null; if(prevNode){ this.setLine(prevNode.item,sliceNode.item); } this.tail = sliceNode; }
清空item链表
将链表清空,item线条全部隐藏
/* 清空链表 */ public clear():void{ let currentNode:Node = this.head; while(currentNode){ currentNode.item.showLine(0); currentNode = currentNode.next; } this.head = null; this.tail = null; this.length = 0; }

浙公网安备 33010602011771号