SlideShare ist ein Scribd-Unternehmen logo
1 von 76
Downloaden Sie, um offline zu lesen
Greenfoot 接龍(四)
  遊戲的操作與控制


      依瑪貓/楊士青
imacat@mail.imacat.idv.tw
       2012/6/29
「接龍遊戲—由上而下的物件導向程式設計」簡報由 依瑪貓╱楊士青 製作,
 以 創用CC Attribution-ShareAlike 3.0 Unported 授權條款 釋出。
自我介紹
依瑪貓╱楊士青
臺灣師範大學資訊教育研究所碩一研究生
如果你前面的練習順利完成,
   可以繼續做下去。
 不然請開啟 solitaire-4 。
把接龍寫成遊戲
想一想



接龍遊戲寫到現在,
 我們完成了什麼?
  還缺什麼?
我們完成了什麼?
遊戲的設計
遊戲的邏輯與規則
我們還缺什麼?
遊戲的操作與控制
 接龍不是這樣子玩的!
想一想




接龍是怎麼玩的?
(本頁留白)
(請勿往後偷看)
接龍的玩法
在撲克牌背上點一下滑鼠翻牌。
用滑鼠拖拉撲克牌移牌。
在牌背上點一下滑鼠翻牌
在牌背上點一下滑鼠翻牌
其實是點在撲克牌上,不是點在牌疊上。
 寫在 Card 的 act() 方法中,不是寫在 Pile 的
  act() 方法中。
翻牌的條件規則
被點到的牌,牌面原來朝下,未翻開。
被點到的牌,是牌疊最上面的一張牌。
只有兩種牌疊有關:
 未翻開的牌疊:翻開到已翻開的排疊。我們之前
  已經寫過 flipNextCard()
 暫存區的牌疊:翻開之後,不需要移動牌疊。
翻牌的條件規則
public class Card extends Actor
{
    public void act()
    {
        // 牌面朝下,翻牌。
        if (!isFaceUp) {
            if (Greenfoot.mouseClicked(this) && this == pile.getTopCard()) {
                if (pile instanceof UnflippedPile) {
                    ((UnflippedPile) pile).flipNextCard();
                } else if (pile instanceof WorkingPile) {
                    ((WorkingPile) pile).flipTopCard();
                }
            }
        }
    }
}
instanceof
判斷某物件是不是某類別。
 WorkingPile x instanceof WorkingPile
 WorkingPile x instanceof Pile
 Card y instanceof Pile?
((WorkingPile) pile).flip()
原來 pile 欄位的型態是 Pile , Pile 沒有
 flipTopCard() 方法,只有 WorkingPile
 有 flipTopCard() 方法。
不過我們知道這時的 pile 是個
 WorkingPile (由 instanceof 檢查)。
先強制型別轉換: (WorkingPile) pile 。
轉換後再執行 flipTopCard() 方法。
例外:重新翻牌
未翻開牌都翻出來時,再點一次重新翻牌。
 這時候再點一次時,點到的地方沒有牌了
 ,露出的被壓在底下的未翻開牌疊。
 點到未翻開牌疊時,退回所有的牌,這時候點到
  的不是撲克牌,而是牌疊。
例外:重新翻牌




試著自己實作看看!
(本頁留白)
(請勿往後偷看)
重新翻牌
public class UnflippedPile extends Pile
{
    …
    public void act()
    {
        // 點到牌疊的空位時,就已經沒有牌了,重新翻牌。
        if (Greenfoot.mouseClicked(this))
        {
            Table table = (Table) getWorld();
            table.getFlippedPile().returnAllCards();
        }
    }
}
試著執行看看!
       要先按暫停,
按滑鼠右鍵執行 moveToWorking() 將
    牌移開,再繼續執行,
     才能試翻下面的牌。
用滑鼠拖拉撲克牌移牌
用滑鼠拖拉撲克牌移牌
試著用滑鼠移動拖拉
 撲克牌移牌,你觀
 察到了什麼?
用滑鼠拖拉撲克牌移牌
撲克牌拖拉時,分裂
 出了一個牌疊,分
 裂出來的牌疊,隨
 著滑鼠而移動。
我們其實還有一種牌疊,
    平常沒有,
 拖拉移牌時才會出現,
 並且會隨著滑鼠移動。
用滑鼠拖拉撲克牌移牌



請新增一個牌疊 subclass 子類別,
  取名叫做 MovingPile 。
用滑鼠拖拉撲克牌移牌




讓牌疊的位置,跟著滑鼠的位置移動。
用滑鼠拖拉撲克牌移牌



  每回合 act() 的時候,
都把牌疊移到目前滑鼠的位子上。
MovingPile
public class MovingPile extends Pile
{
    /**
     * 每回合執行的動作。
     */
    public void act()
    {
          MouseInfo mouse = Greenfoot.getMouseInfo();
          setLocation(mouse.getX(), mouse.getY());
    }
}
MovingPile
    (如果是 Greenfoot 2.1.1 )
public class MovingPile extends Pile
{
    /**
     * 每回合執行的動作。
     */
    public void act()
    {
          MouseInfo mouse = Greenfoot.getMouseInfo();
          If (mouse != null) {
              setLocation(mouse.getX(), mouse.getY());
          }
    }
}
MouseInfo
MouseInfo
查看 Greenfoot API
 文件,看看
 MouseInfo 是什麼
 ?有哪些工具功能
 ?
MouseInfo
可以用 getX() 和 getY() 取得現在的滑鼠座
 標。
用滑鼠拖拉撲克牌移牌
試著執行看看!
 按執行。
 執行時由右邊產生
  MovingPile 。
 滑鼠移到桌面上新增
  移動牌堆。
剩下的工作
想一想



有了會隨滑鼠移動的移動牌疊,
  剩下的工作,是什麼?
(本頁留白)
(請勿往後偷看)
剩下的工作
拖拉開始時,開始移動:
 產生新的移動牌疊。
 把牌移到移動牌疊上。
拖拉結束後,結束移動:
 把牌移到滑鼠所在的牌疊,或退回到原牌疊。
 刪掉結束功能的移動牌疊。
拖拉結束後,如果無法移牌時,
   撲克牌要退回原牌疊。
 所以要記得原牌疊是哪一疊。
拖拉開始時,開始移動
拖拉開始時,開始移動
和前面翻牌同理,拖拉時拉的是撲克牌,不
 是牌疊。
拖拉開始時,開始移動
只要翻開來的牌,都可以開始移動。其實不
 限於哪個牌疊。
 所以我們把「 startMoving() 開始移動」寫在
  Pile 裏,所有牌疊共同繼承共用,不限於哪個
  牌疊。
拖拉開始時,開始移動
點到一疊中間的牌時(暫存牌區),那張牌
 起,疊在它上面的牌都需一起移動。
拖拉開始時,開始移動
        (這裏蓋掉之前寫的前兩行)
public class Card extends Actor

{

    …

    private boolean isDragging = false;

    public void act()

    {

        // 牌面朝上,移動撲克牌。

        if (isFaceUp) {

            if (!isDragging && Greenfoot.mouseDragged(this)) {

                isDragging = true;

                pile.startMoving(this);

            }

        // 牌面朝下,翻牌。

        } else {

            if (Greenfoot.mouseClicked(this) && this == pile.getTopCard()) {

                   …

            }

        }

    }

}
拖拉開始時,開始移動
public class Pile extends Actor

{

    public void startMoving(Card starCard)

    {

        int index = -1;

        for (int i = 0; i < getSize(); i++) {

            if (getCard(i) == starCard) {

                index = i;

                break;

            }

        }

        if (index == -1) {

            return;

        }

        MovingPile target = new MovingPile(this);

        MouseInfo mouse = Greenfoot.getMouseInfo();

        getWorld().addObject(target, mouse.getX(), mouse.getY());

        while (index < getSize()) {

            Card card = takeCard(index);

            target.addCard(card);

        }

    }

}
拖拉開始時,開始移動
public class MovingPile extends Pile
{
    /** 撲克牌是由哪一疊移動的。 */
    Pile from = null;


    /**
     * 建立一疊新的移動牌疊。
     *
     * @param from 撲克牌是由哪一疊移動的。
     */
    public MovingPile(Pile from)
    {
          this.from = from;
    }
}
試著執行看看!
怪怪的…
想一想
雖然是移動了,但是
 撲克牌動一下就不
 動了,空留下牌疊
 框隨滑鼠移動。
為什麼呢?
(本頁留白)
(請勿往後偷看)
撲克牌疊移動時,
 撲克牌沒有跟著移動。
撲克牌應該要跟著移動。
撲克牌跟著牌疊一起移動
public class MovingPile extends Pile
{
    /**
     * 每回合執行的動作。
     */
    public void act()
    {
          MouseInfo mouse = Greenfoot.getMouseInfo();
          setLocation(mouse.getX(), mouse.getY());
          redrawCards();
    }
}
撲克牌跟著牌疊一起移動
public class MovingPile extends Pile
{
    /**
     * 重繪牌疊中撲克牌的位置。
     *
     */
    public void redrawCards()
    {
          for (int i = 0; i < getSize(); i++)
          {
              getCard(i).setLocation(getX(), getY() + 3 + 12 * i);
          }
    }
}
試著執行看看!
拖拉結束後,結束移動
拖拉結束後,結束移動


拖拉結束後,看滑鼠落在哪個牌疊,
 檢查看能不能把牌放到那個牌疊。
 如果可以,就把牌放到那個牌疊。
  如果不行,就把牌退回去。
拖拉結束後,結束移動
public class Card extends Actor {

    public void act() {

        if (isFaceUp) {

            if (!isDragging && Greenfoot.mouseDragged(this)) {

                …

            } else if (isDragging && Greenfoot.mouseDragEnded(this)) {

                isDragging = false;

                MovingPile movingPile = (MovingPile) pile;

                Pile target = movingPile.getNowOnPile();

                if (target == null) {

                    movingPile.returnCards();

                } else if (!target.isAcceptCard(this)) {

                    movingPile.returnCards();

                } else {

                    movingPile.moveTo(target);

                }

            }

        }

        …

    }

}
拖拉結束後,結束移動
import java.util.List;
public class MovingPile extends Pile
{
    /**
     * 取得現在移到哪個牌疊。
     *
     * @return 目前滑鼠所在的牌疊。若滑鼠所在沒有牌疊,則傳回 null 。
     */
    public Pile getNowOnPile()
    {
          MouseInfo mouse = Greenfoot.getMouseInfo();
          List<Pile> piles = getWorld().getObjectsAt(mouse.getX(), mouse.getY(), Pile.class);
          piles.remove(this);     // 排除 掉自己 MovingPile 。
          if (piles.size() == 0) {
              return null;
          }
          return piles.get(0);
    }
}
isAcceptCard()
原本我們只有暫存牌疊 WorkingPile 和歸整
 牌疊 ResultPile 有 isAcceptCard() 。
為方便起見,我們寫下父類別 Pile 的
 isAcceptCard() ,預設是拒絕。然後再讓
 WorkingPile 及 ResultPile 覆寫 override
 父類別的 isAcceptCard() 。
isAcceptCard()
public class Pile extends Actor
{
    /**
     * 是否接受移入撲克牌?一定會傳回否。
     *
     * @param card 要移入的撲克牌
     * @return 是否接受移入撲克牌。一定會傳回否。
     */
    public boolean isAcceptCard(Card card)
    {
          return false;
    }
}
returnCards() 和 moveTo()
撲克牌由 MovingPile 移出去的時候,是由
 下往上抽出來,不是由上往下抽牌。
takeBottomCard()
public class MovingPile extends Pile
{
    /**
     * 抽掉下面的撲克牌。會同時把牌從牌桌移掉。牌疊空了的時候,會得到 null 。
     *
     * @return 最下面的撲克牌
     */
    public Card takeBottomCard()
    {
          if (getSize() == 0)
          {
              return null;
          }
          return takeCard(0);
    }
}
returnCards() 和 moveTo()




       試著實作看看!
(本頁留白)
(請勿往後偷看)
returnCards()
public class MovingPile extends Pile
{
    /**
     * 把撲克牌退回來源牌疊。牌退回去後,會把這個移動牌疊從牌桌刪掉。
     *
     */
    public void returnCards()
    {
          while (getSize() > 0)
          {
              Card card = takeBottomCard();
              from.addCard(card);
          }
          getWorld().removeObject(this);
    }
}
moveTo()
public class MovingPile extends Pile
{
    /**
     * 把撲克牌移到目的地的牌疊。牌移過去後,會把這個移動牌疊從牌桌刪掉。
     *
     * @param target 目的地的牌疊
     */
    public void moveTo(Pile target)
    {
          while (getSize() > 0)
          {
              Card card = takeBottomCard();
              target.addCard(card);
          }
          getWorld().removeObject(this);
    }
}
試著執行看看!
如果你上面的練習都做得正確,
程式應該會長得像 solitaire-5 一樣。
想一想



還有什麼地方可以改進呢?
  可以怎麼修改?
(本頁留白)
(請勿往後偷看)
可以改進的地方


     移到暫存區時,
滑鼠要移到最上方的牌疊方框才可以。
 和我們的視覺操作的直覺不一樣,
     可以怎麼改進?
可以改進的地方



   移牌時,牌疊會晃一下,
移動牌疊中心點,對齊到滑鼠位置。
有沒有辦法避免這個不必要的晃動?
可以改進的地方



為了教學,才使用左上角凸一塊的牌疊底
        圖,
   可以改用正常的牌疊底圖嗎?
可以改進的地方




可以加個計時器嗎?
謝謝大家。
歡迎提出問題。

Weitere ähnliche Inhalte

Andere mochten auch

Fases de la entrevista
Fases de la entrevistaFases de la entrevista
Fases de la entrevistarutgear
 
funkciju skaiciavimas ir ju grafikai
funkciju skaiciavimas ir ju grafikaifunkciju skaiciavimas ir ju grafikai
funkciju skaiciavimas ir ju grafikaiddaiva
 

Andere mochten auch (20)

steen hvass
steen hvasssteen hvass
steen hvass
 
Cooker book_ sun tracking
Cooker book_ sun trackingCooker book_ sun tracking
Cooker book_ sun tracking
 
81 birgitte faurh+©jolsen_en sten kom for dagen
81 birgitte faurh+©jolsen_en sten kom for dagen81 birgitte faurh+©jolsen_en sten kom for dagen
81 birgitte faurh+©jolsen_en sten kom for dagen
 
25 sarah quistgaard_sjelborg
25 sarah quistgaard_sjelborg25 sarah quistgaard_sjelborg
25 sarah quistgaard_sjelborg
 
121 inge meretekjeldgaard_det kunstneriske blik
121 inge meretekjeldgaard_det kunstneriske blik121 inge meretekjeldgaard_det kunstneriske blik
121 inge meretekjeldgaard_det kunstneriske blik
 
66 henriette rensbro_m+ñrup kirke
66 henriette rensbro_m+ñrup kirke66 henriette rensbro_m+ñrup kirke
66 henriette rensbro_m+ñrup kirke
 
57 anders hartvig_diger og g+©dning i t+©nder
57 anders hartvig_diger og g+©dning i t+©nder57 anders hartvig_diger og g+©dning i t+©nder
57 anders hartvig_diger og g+©dning i t+©nder
 
Fases de la entrevista
Fases de la entrevistaFases de la entrevista
Fases de la entrevista
 
Karin Poulsen - håndværkerbebyggelse
Karin Poulsen -  håndværkerbebyggelseKarin Poulsen -  håndværkerbebyggelse
Karin Poulsen - håndværkerbebyggelse
 
103 lars juelthiis_museer
103 lars juelthiis_museer103 lars juelthiis_museer
103 lars juelthiis_museer
 
Charlie Christensen
Charlie ChristensenCharlie Christensen
Charlie Christensen
 
72 gitte engholm_nm indsamlingsprojekt om syriske flygtninge
72 gitte engholm_nm indsamlingsprojekt om syriske flygtninge72 gitte engholm_nm indsamlingsprojekt om syriske flygtninge
72 gitte engholm_nm indsamlingsprojekt om syriske flygtninge
 
109 ilsevan zeeland_collection in new naturalis
109 ilsevan zeeland_collection in new naturalis109 ilsevan zeeland_collection in new naturalis
109 ilsevan zeeland_collection in new naturalis
 
Anders Hartvig
Anders HartvigAnders Hartvig
Anders Hartvig
 
10x7 10 Viking Gitte Engholm
10x7 10 Viking Gitte Engholm10x7 10 Viking Gitte Engholm
10x7 10 Viking Gitte Engholm
 
8 Jane Alexander, Chief Information Officer for Cleveland Museum of Art
8 Jane Alexander, Chief Information Officer for Cleveland Museum of Art8 Jane Alexander, Chief Information Officer for Cleveland Museum of Art
8 Jane Alexander, Chief Information Officer for Cleveland Museum of Art
 
79 anders abildgaard_restaurering af glasloft
79 anders abildgaard_restaurering af glasloft79 anders abildgaard_restaurering af glasloft
79 anders abildgaard_restaurering af glasloft
 
13 dobat dime
13 dobat dime13 dobat dime
13 dobat dime
 
32 kent laursen_lauritsh+©j ii
32 kent laursen_lauritsh+©j ii32 kent laursen_lauritsh+©j ii
32 kent laursen_lauritsh+©j ii
 
funkciju skaiciavimas ir ju grafikai
funkciju skaiciavimas ir ju grafikaifunkciju skaiciavimas ir ju grafikai
funkciju skaiciavimas ir ju grafikai
 

Mehr von imacat .

A Room of WikiWomen's Own
A Room of WikiWomen's OwnA Room of WikiWomen's Own
A Room of WikiWomen's Ownimacat .
 
Office寶可夢GO IV計算機
Office寶可夢GO IV計算機Office寶可夢GO IV計算機
Office寶可夢GO IV計算機imacat .
 
Crossing Office Applications
Crossing Office ApplicationsCrossing Office Applications
Crossing Office Applicationsimacat .
 
OpenOffice Application with Python
OpenOffice Application with PythonOpenOffice Application with Python
OpenOffice Application with Pythonimacat .
 
從doc、docx、odt到Google Docs
從doc、docx、odt到Google Docs從doc、docx、odt到Google Docs
從doc、docx、odt到Google Docsimacat .
 
More Girls – Creating a Community of Diversity
More Girls – Creating a Community of DiversityMore Girls – Creating a Community of Diversity
More Girls – Creating a Community of Diversityimacat .
 
Welcome to Apache OpenOffice 4
Welcome to Apache OpenOffice 4Welcome to Apache OpenOffice 4
Welcome to Apache OpenOffice 4imacat .
 
OpenOffice, Open Business
OpenOffice, Open BusinessOpenOffice, Open Business
OpenOffice, Open Businessimacat .
 
Multimedia Fun with OpenOffice Calc
Multimedia Fun with OpenOffice CalcMultimedia Fun with OpenOffice Calc
Multimedia Fun with OpenOffice Calcimacat .
 
Welcome to Apache OpenOffice 3.4 COSCUP 2012
Welcome to Apache OpenOffice 3.4 COSCUP 2012Welcome to Apache OpenOffice 3.4 COSCUP 2012
Welcome to Apache OpenOffice 3.4 COSCUP 2012imacat .
 
Mosaic Fun with OpenOffice Calc
Mosaic Fun with OpenOffice CalcMosaic Fun with OpenOffice Calc
Mosaic Fun with OpenOffice Calcimacat .
 
GNU Autoconf / Automake #4
GNU Autoconf / Automake #4GNU Autoconf / Automake #4
GNU Autoconf / Automake #4imacat .
 
GNU Autoconf / Automake #1
GNU Autoconf / Automake #1GNU Autoconf / Automake #1
GNU Autoconf / Automake #1imacat .
 
Solitaire with Greenfoot #3
Solitaire with Greenfoot #3Solitaire with Greenfoot #3
Solitaire with Greenfoot #3imacat .
 
Solitaire with Greenfoot #2
Solitaire with Greenfoot #2Solitaire with Greenfoot #2
Solitaire with Greenfoot #2imacat .
 
Solitaire with Greenfoot #2/4
Solitaire with Greenfoot #2/4Solitaire with Greenfoot #2/4
Solitaire with Greenfoot #2/4imacat .
 
Object-Oriented Programming Design with Greenfoot 02
Object-Oriented Programming Design with Greenfoot 02Object-Oriented Programming Design with Greenfoot 02
Object-Oriented Programming Design with Greenfoot 02imacat .
 
Welcome to Apache OpenOffice 3.4
Welcome to Apache OpenOffice 3.4Welcome to Apache OpenOffice 3.4
Welcome to Apache OpenOffice 3.4imacat .
 
OpenOffice UNO Application on Android
OpenOffice UNO Application on AndroidOpenOffice UNO Application on Android
OpenOffice UNO Application on Androidimacat .
 
OpenOffice.org Magic Sandbox
OpenOffice.org Magic SandboxOpenOffice.org Magic Sandbox
OpenOffice.org Magic Sandboximacat .
 

Mehr von imacat . (20)

A Room of WikiWomen's Own
A Room of WikiWomen's OwnA Room of WikiWomen's Own
A Room of WikiWomen's Own
 
Office寶可夢GO IV計算機
Office寶可夢GO IV計算機Office寶可夢GO IV計算機
Office寶可夢GO IV計算機
 
Crossing Office Applications
Crossing Office ApplicationsCrossing Office Applications
Crossing Office Applications
 
OpenOffice Application with Python
OpenOffice Application with PythonOpenOffice Application with Python
OpenOffice Application with Python
 
從doc、docx、odt到Google Docs
從doc、docx、odt到Google Docs從doc、docx、odt到Google Docs
從doc、docx、odt到Google Docs
 
More Girls – Creating a Community of Diversity
More Girls – Creating a Community of DiversityMore Girls – Creating a Community of Diversity
More Girls – Creating a Community of Diversity
 
Welcome to Apache OpenOffice 4
Welcome to Apache OpenOffice 4Welcome to Apache OpenOffice 4
Welcome to Apache OpenOffice 4
 
OpenOffice, Open Business
OpenOffice, Open BusinessOpenOffice, Open Business
OpenOffice, Open Business
 
Multimedia Fun with OpenOffice Calc
Multimedia Fun with OpenOffice CalcMultimedia Fun with OpenOffice Calc
Multimedia Fun with OpenOffice Calc
 
Welcome to Apache OpenOffice 3.4 COSCUP 2012
Welcome to Apache OpenOffice 3.4 COSCUP 2012Welcome to Apache OpenOffice 3.4 COSCUP 2012
Welcome to Apache OpenOffice 3.4 COSCUP 2012
 
Mosaic Fun with OpenOffice Calc
Mosaic Fun with OpenOffice CalcMosaic Fun with OpenOffice Calc
Mosaic Fun with OpenOffice Calc
 
GNU Autoconf / Automake #4
GNU Autoconf / Automake #4GNU Autoconf / Automake #4
GNU Autoconf / Automake #4
 
GNU Autoconf / Automake #1
GNU Autoconf / Automake #1GNU Autoconf / Automake #1
GNU Autoconf / Automake #1
 
Solitaire with Greenfoot #3
Solitaire with Greenfoot #3Solitaire with Greenfoot #3
Solitaire with Greenfoot #3
 
Solitaire with Greenfoot #2
Solitaire with Greenfoot #2Solitaire with Greenfoot #2
Solitaire with Greenfoot #2
 
Solitaire with Greenfoot #2/4
Solitaire with Greenfoot #2/4Solitaire with Greenfoot #2/4
Solitaire with Greenfoot #2/4
 
Object-Oriented Programming Design with Greenfoot 02
Object-Oriented Programming Design with Greenfoot 02Object-Oriented Programming Design with Greenfoot 02
Object-Oriented Programming Design with Greenfoot 02
 
Welcome to Apache OpenOffice 3.4
Welcome to Apache OpenOffice 3.4Welcome to Apache OpenOffice 3.4
Welcome to Apache OpenOffice 3.4
 
OpenOffice UNO Application on Android
OpenOffice UNO Application on AndroidOpenOffice UNO Application on Android
OpenOffice UNO Application on Android
 
OpenOffice.org Magic Sandbox
OpenOffice.org Magic SandboxOpenOffice.org Magic Sandbox
OpenOffice.org Magic Sandbox
 

Solitaire with Greenfoot #4