我的新書AI 職場超神助手:ChatGPT 與生成式 AI 一鍵搞定工作難題的教材投影片已製作完成
歡迎各位有需要的教師和博碩文化索取教材

[6 – 遊戲邏輯] 連線消除程式撰寫

主要遊戲流程

連連看點選兩個圖案後,可消除的邏輯是:

  • 兩個所點擊到的圖案相同
  • 連線不超過兩個轉彎

因此我們先來寫遊戲主流程的部份,玩家會先點第一個圖案,代表他想要消除這個圖案,接著再消第二個圖案,這時再來判斷是否符合可消除,這部份的流程圖如下:

撰寫的程式碼如下

var app = angular.module('LianLianKan', []);
app.controller('myCtrl', function ($scope) {
    $scope.select1 = new Point(-1, -1);
    $scope.select2 = new Point(-1, -1);
    $scope.selected = false;
    let msgArra = [];
    $scope.message = msgArra;
    let board = new Board();
    $scope.boardContent = board.board;
    $scope.click = function (x: number, y: number) {
        if ($scope.selected) {
            $scope.select2 = new Point(x, y);
            if (board.hasSameValue($scope.select1, $scope.select2)) {


                if (! ($scope.select1.x == x && $scope.select1.y == y) ) {//確認所選的兩個點不一樣

                    let path = new Path($scope.select1, $scope.select2, board);
                    if(path.canLinkInLine()){
                        board.clearPoint($scope.select1);
                        board.clearPoint($scope.select2);
                        msgArra.push(path);
                    }
                }
            }
            $scope.selected = false;
        } else {
            $scope.select1 = new Point(x, y);
            $scope.selected = true;
        }
    };
});

判斷所選圖案是否相同

在上面的程式碼中,可以看到我們用board.hasSameValue($scope.select1, $scope.select2)來判斷所選的圖是是否相同。我們可以Board的類別增加public hasSameValue(point1: Point, point2: Point): boolean如下:

    public hasSameValue(point1: Point, point2: Point): boolean {
        return this.board[point1.x][point1.y] == this.board[point2.x][point2.y];
    }

連線邏輯撰寫

新建一個類別Path內容如下
class Path {
public point1: Point;
public point2: Point;
readonly board: Board;
public path_Detail:Array;

constructor(point1: Point, point2: Point, board: Board) {
this.point1 = point1;
this.point2 = point2;
this.board = board;
}

public canLinkInLine(): boolean {

console.log(“board”,this.board);

//從上面消
//兩個點都往上找最遠能到達的距離
let point1UP = this.board.getNearByPointByDirection(this.point1, Direction.UP);
let point2UP = this.board.getNearByPointByDirection(this.point2, Direction.UP);
console.log(“point1UP”,point1UP,”point2UP”,point2UP);
//尋找這之中可能存在的路徑
{
let min = Math.max(point1UP.x,point2UP.x);
let max = Math.min(this.point1.x, this.point2.x);
for (var i = max;i>=min;i–){
if (!this.board.hasMiddleValue(new Point(i, this.point1.y), new Point(i, this.point2.y))){
this.path_Detail = [this.point1,new Point(i, this.point1.y),new Point(i, this.point2.y),this.point2];
console.log(“same up”);
return true;
}
}
}
//從下面消
let point1DOWN = this.board.getNearByPointByDirection(this.point1, Direction.DOWN);
let point2DOWN = this.board.getNearByPointByDirection(this.point2, Direction.DOWN);
console.log(“point1DOWN”,point1DOWN,”point2DOWN”,point2DOWN);
{
let max = Math.min(point1DOWN.x,point2DOWN.x);
let min = Math.max(this.point1.x, this.point2.x);
for (var i = min;i<=max;i++){ if (!this.board.hasMiddleValue(new Point(i, this.point1.y), new Point(i, this.point2.y))){ this.path_Detail = [this.point1,new Point(i, this.point1.y),new Point(i, this.point2.y),this.point2]; console.log("same down"); return true; } } } //從左邊消 let point1LEFT = this.board.getNearByPointByDirection(this.point1, Direction.LEFT); let point2LEFT = this.board.getNearByPointByDirection(this.point2, Direction.LEFT); console.log("point1LEFT",point1LEFT,"point2LEFT",point2LEFT); { let min = Math.max(point1LEFT.y,point2LEFT.y); let max = Math.min(this.point1.y, this.point2.y); for (var i = max;i>=min;i–) {
if (!this.board.hasMiddleValue(new Point(this.point1.x, i), new Point(this.point2.x, i))) {
this.path_Detail = [this.point1, new Point(this.point1.x, i), new Point(this.point2.x, i), this.point2];
console.log(“same left”);
return true;
}
}
}

//從右邊消
let point1RIGHT = this.board.getNearByPointByDirection(this.point1, Direction.RIGHT);
let point2RIGHT = this.board.getNearByPointByDirection(this.point2, Direction.RIGHT);
console.log(“point1RIGHT”,point1RIGHT,”point2RIGHT”,point2RIGHT);
{
let max = Math.min(point1RIGHT.y,point2RIGHT.y);
let min = Math.max(this.point1.y, this.point2.y);
for (var i = min;i<=max;i++) { if (!this.board.hasMiddleValue(new Point(this.point1.x, i), new Point(this.point2.x, i))) { this.path_Detail = [this.point1, new Point(this.point1.x, i), new Point(this.point2.x, i), this.point2]; console.log("same right"); return true; } } } //左右連消 if (this.point1.y != this.point2.y){ //先判斷那個點在左,那個點在右 let leftPoint = (this.point1.y < this.point2.y) ? this.point1:this.point2; let rightPoint = (this.point1.y >= this.point2.y) ? this.point1:this.point2;
//取得右邊的點,直線往左最左的那個點
let leftPointRIGHT = this.board.getNearByPointByDirection(leftPoint, Direction.RIGHT);
let rightPointLEFT = this.board.getNearByPointByDirection(rightPoint, Direction.LEFT);
//參考前一篇文章的圖,右邊最左的點不可超過左邊的點,否則會造成誤判
leftPointRIGHT.y = (leftPointRIGHT.y < rightPoint.y) ? leftPointRIGHT.y : rightPoint.y; rightPointLEFT.y = (rightPointLEFT.y > leftPoint.y) ? rightPointLEFT.y : leftPoint.y;
//用迴圈判斷在所有有可能的範圍中是否有可能存在的路徑
if (leftPointRIGHT.y != leftPoint.y && rightPointLEFT.y != rightPoint.y){
for (var i = rightPointLEFT.y; i <= leftPointRIGHT.y; i++) { if (!this.board.hasMiddleValue(new Point(leftPoint.x, i), new Point(rightPoint.x, i))) { this.path_Detail = [leftPoint, new Point(leftPoint.x, i), new Point(rightPoint.x, i), rightPoint]; console.log("same left to right"); return true; } } } } //上下連消 if (this.point1.x != this.point2.x){ let upPoint = (this.point1.x < this.point2.x) ? this.point1:this.point2; let downPoint = (this.point1.x >= this.point2.x) ? this.point1:this.point2;
let upPointDOWN = this.board.getNearByPointByDirection(upPoint, Direction.DOWN);
let downPointUP = this.board.getNearByPointByDirection(downPoint, Direction.UP);
upPointDOWN.x = (upPointDOWN.x < downPoint.x) ? upPointDOWN.x : downPoint.x; downPointUP.x = (downPointUP.x > upPoint.x) ? downPointUP.x : upPoint.x;
if (upPointDOWN.x != upPoint.x && downPointUP.x != downPoint.x){
for (var i = downPointUP.x; i <= upPointDOWN.x; i++) { if (!this.board.hasMiddleValue(new Point(i, upPoint.y), new Point(i, downPoint.y))) { this.path_Detail = [upPoint, new Point(i, upPoint.y), new Point(i, downPoint.y), downPoint]; console.log("same top to down"); return true; } } } } return false; } }[/code] 新增類別Board

class Board {
public board: Array>;

constructor() {
let content = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25];
//產生初始局面
let length = 10;
let data = content.concat(content).concat(content).concat(content).sort((a, b) => (Math.random() > .5) ? 1 : 0);
this.board = []
for (var i = 0;i= 0; i–) {
if (this.board[i][point.y] == null) {
nearByPoint.x = i;
} else {
break;
}
}
if (nearByPoint.x == 0) {
nearByPoint.x = -1;
}
break;
case Direction.DOWN:
//搜尋往下走最遠可到達的點
let maxLengthDOWN = this.board.length;
for (var i = point.x+1; i < maxLengthDOWN; i++) { if (this.board[i][point.y] == null) { nearByPoint.x = i; } else { break; } } if (nearByPoint.x == maxLengthDOWN - 1) { nearByPoint.x = maxLengthDOWN; } break; case Direction.RIGHT: //搜尋往右走最遠可到達的點 let maxLengthRIGHT = this.board[0].length; for (var i = point.y+1; i < maxLengthRIGHT; i++) { if (this.board[point.x][i] == null) { nearByPoint.y = i; } else { break; } } if (nearByPoint.y == maxLengthRIGHT - 1) { nearByPoint.y = maxLengthRIGHT; } break; case Direction.LEFT: //搜尋往左走最遠可到達的點 for (var i = point.y-1; i >= 0; i–) {
if (this.board[point.x][i] == null) {
nearByPoint.y = i;
} else {
break;
}
}
if (nearByPoint.y == 0) {
nearByPoint.y = -1;
}
break;
}
return nearByPoint;
}

//搜尋在兩個點之中是否可以找到一直線可連接
public canFindPath(a: Point, b: Point, direction:string): boolean {
return this.hasMiddleValue(a ,b);
}

//偵測在兩個點中是否可用一條直線做連接
public hasMiddleValue(a: Point, b: Point): boolean {
let arr = [];
if (a.x == b.x) {
if (a.x == -1 || a.x == this.board.length) return false;
let max = Math.max(a.y, b.y);
let min = Math.min(a.y, b.y);
for (var i = min + 1; i < max; i++) { if (this.board[a.x][i] != null) { return true; } } return false; } else if (a.y == b.y) { if (a.y == -1 || a.y == this.board[0].length) return false; let max = Math.max(a.x, b.x); let min = Math.min(a.x, b.x); for (var i = min + 1; i < max; i++) { if (this.board[i][a.y] != null) { return true; } } return false; } else { return true; } } //判斷某兩個點的值是否相同 public hasSameValue(point1: Point, point2: Point): boolean { return this.board[point1.x][point1.y] == this.board[point2.x][point2.y]; } //將盤面上的圖消掉 public clearPoint(point: Point) { this.board[point.x][point.y] = null; point = null; } } [/code] 今日成果:
Live Demo:今日成果展示
今天的專案可至此下載:ironman20181021


17年資歷女工程師,專精於動畫、影像辨識以及即時串流程式開發。經常組織活動,邀請優秀的女性分享她們的技術專長,並在眾多場合分享自己的技術知識,也活躍於非營利組織,辦理活動來支持特殊兒及其家庭。期待用技術改變世界。

如果你認同我或想支持我的努力,歡迎請我喝一杯咖啡!讓我更有動力分享知識!